useFetch
🐶 React hook for making isomorphic http requests
Need to fetch some data? Try this one out. It's an isomorphic fetch hook. That means it works with SSR (server side rendering).
A note on the documentation below. Many of these examples could have performance improvements using useMemo
and useCallback
, but for the sake of the beginner/ease of reading, they are left out.
Features
- SSR (server side rendering) support
- TypeScript support
- 1 dependency (use-ssr)
- GraphQL support (queries + mutations)
- Provider to set default
url
andoptions
Examples
Installation
yarn add use-http or npm i -S use-http
Usage
Basic Usage
import useFetch from 'use-http' { const options = // accepts all `fetch` options onMount: true // will fire on componentDidMount const todos = { todos } if todoserror return 'Error!' if todosloading return 'Loading...' return <> <button =>Add Todo</button> todosdata
Destructured
var data loading error request = // want to use object destructuring? You can do that toovar data loading error request =
Relative routes
const request = request
Helper hooks
import useGet usePost usePatch usePut useDelete from 'use-http' const data loading error patch =
Abort
const githubRepos = // the line below is not isomorphic, but for simplicity we're using the browsers `encodeURI`const searchGithubRepos = githubRepos <> <input = /> <button =>Abort</button> githubReposloading ? 'Loading...' : githubReposdataitems</>
GraphQL Query
const QUERY = ` query Todos($userID string!) { todos(userID: $userID) { id title } }` { const request = const getTodosForUser = request return <> <button =>Get Todos</button> requestloading ? 'Loading...' : <pre>requestdata</pre> </> }
GraphQL Mutation
const MUTATION = ` mutation CreateTodo($todoTitle string) { todo(title: $todoTitle) { id title } }` { const todoTitle setTodoTitle = const request = const createtodo = request return <> <input = /> <button =>Create Todo</button> requestloading ? 'Loading...' : <pre>requestdata</pre> </> }
Provider
using the GraphQL useMutation
and useQuery
The Provider
allows us to set a default url
, options
(such as headers) and so on.
Query for todos
import Provider useQuery useMutation from 'use-http' { const request = useQuery` query Todos($userID string!) { todos(userID: $userID) { id title } } ` const getTodosForUser = request return <> <button =>Get Todos</button> requestloading ? 'Loading...' : <pre>requestdata</pre> </> }
Add a new todo
{ const todoTitle setTodoTitle = const data loading error mutate = useMutation` mutation CreateTodo($todoTitle string) { todo(title: $todoTitle) { id title } } ` const createTodo = return <> <input = /> <button =>Create Todo</button> loading ? 'Loading...' : <pre>data</pre> </> }
Adding the Provider
These props are defaults used in every request inside the <Provider />
. They can be overwritten individually
{ const options = headers: Authorization: 'Bearer:asdfasdfasdfasdfasdafd' return <Provider ='http://example.com' => <QueryComponent /> <MutationComponent /> <Provider/> }
The Goal With Suspense (not implemented yet)
import React Suspense unstable_ConcurrentMode as ConcurrentMode useEffect from 'react' { const suspense = if !suspensedata return null return <pre>suspensedata</pre>} ( <ConcurrentMode> <Suspense fallback="Loading..."> <WithSuspense /> </Suspense> </ConcurrentMode>)
Hooks
Option | Description |
---|---|
useFetch |
The base hook |
useGet |
Defaults to a GET request |
usePost |
Defaults to a POST request |
usePut |
Defaults to a PUT request |
usePatch |
Defaults to a PATCH request |
useDelete |
Defaults to a DELETE request |
useQuery |
For making a GraphQL query |
useMutation |
For making a GraphQL mutation |
Options
This is exactly what you would pass to the normal js fetch
, with a little extra.
Option | Description | Default |
---|---|---|
onMount |
Once the component mounts, the http request will run immediately | false |
baseUrl |
Allows you to set a base path so relative paths can be used for each request :) | empty string |
const data loading error request get post patch put delete // don't destructure `delete` though, it's a keyword del // <- that's why we have this (del). or use `request.delete` abort query // GraphQL mutate // GraphQL} =
or
const data loading error request = const get post patch put delete // don't destructure `delete` though, it's a keyword del // <- that's why we have this (del). or use `request.delete` abort query // GraphQL mutate // GraphQL} = request
Credits
use-http is heavily inspired by the popular http client axios
Feature Requests/Ideas
If you have feature requests, let's talk about them in this issue!
Todos
- port to typescript
- badges
- if no url is specified, and we're in the browser, use
window.location.origin
- support for a global context config where you can set base url's (like Apollo's
client
) but better 😉 - add GraphQL
useQuery
,useMutation
- Make work with React Suspense current example WIP
- make work with FormData
- get it all working on a SSR codesandbox, this way we can have api to call locally
- Allow option to fetch on server instead of just having
loading
state - add
timeout
- add
debounce
- maybe add a
retries: 3
which would specify the amount of times it should retry before erroring out - tests
- ERROR handling:
- if doing
useQuery('my query')
without specifiying a URL in the Provider, throw error - make sure
options
(as 2nd param) to all hooks is an object, if notinvariant
/throw error
- if doing
- add array destructuring return types
- github page/website for docs + show comparison with Apollo
- fix code so Maintainability is A
- optimize badges see awesome badge list
- make GraphQL work with React Suspense
- make GraphQL examples in codesandbox
- make cool logo 😜 I kinda want it to move like this one
- maybe add syntax for custom headers like this
const user = user
Mutations with Suspense (Not Implemented Yet)
const App = const todoTitle setTodoTitle = // if there's no <Provider /> used, useMutation works this way const mutation = // ideally, I think it should be mutation.write({ todoTitle }) since mutation ~= POST const createTodo = mutation if !requestdata return null return <> <input = /> <button =>Create Todo</button> <pre>mutationdata</pre> </>