useFetch: A Custom React Hook
One of the most common React Hooks that I’ve found myself using is one to handle API calls. Often we see ourselves writing almost the same codes in more than one different component. Ideally what we could do in such cases would be to extract that recurrent logic into a reusable piece of code (hook) and reuse it where the need be.
This custom hook will support/include these features:
- Loading Indicator
- Error Handling
- Using On didMount or Some After
- Dynamic Url
- Dynamic Parameters
- Manual Refetch
To convert this example to a custom hook, it would look like this:
This is a very basic example that has many issues; not including handling errors, loading indicator, etc. It’s already quite a bit few lines of code and is not reusable.
Our component could then call it like this:
Let's start to add the features I mentioned above.
Loading Indicator
The loading indicator is a must in my opinion. Because knowing the fetch process still goes on, we can show a loading component or an icon or something else for a nice user experience.
Let's define a state for loading to achieve that.
Our component could use it like this:
Error Handling
Here is another must feature for our custom hook. We’ll define 2 states, one is a boolean value that indicates whether has an error or not and another one is a string value that includes the error message.
We’ll be also using the
try/catch
syntax to set and handle error boundaries. It would look like this:Our component could use it like this:
Using On didMount or Some After
What if we would like to use this hook some after the component renders rather than the didMount stage? To achieve this, we can use a prop (let's say: skip) to skip the data fetching function.
We’ll define itfalse
by default to use fetching on didMount stage.
Our component could use it like this:
Dynamic Url
What if we would like to change the url dynamically to trigger the fetching process again? Why not? Let's implement it.
We’ll change the
url
prop name to initialUrl
to use it as a state. The initialUrl
prop will be the default value of the url
state.We’ll add
url
state to the dependency of the useEffect
hook to trigger it again. Then we’ll export its setState
function which is updateUrl
to use it from our component.Our component could use it like this:
Dynamic Parameters
What about parameters? And what about changing it dynamically to use it like filtering or something else? Sounds great. Let's implement this too.
We’ll take parameters as a prop which will be an object. And then, we’ll transpile them with
encodeURIComponent
to use properly. Following that, we’ll add params
state to the dependency of the useEffect
hook to trigger it again. It would look like this:Our component could use it like this:
Manual Refetch
Another common thing I’ve needed is the ability to manually trigger the API call again. A good example would be a page with a list of resources and wanting to refresh the list from a callback after creating a new resource.
To do this we’ll simply keep a number in the state that’s dependent on the
useEffect
, that we increment every time we want to force a refresh.Finally, it would look like this:
It could be then used in a way similar to this:
Finally
Have you noticed that we're setting
isLoading
state in response.ok
, its else
and catch
cases? Let's use finally
syntax for better development. It'll look like this:Conclusion
In this post, I have explained and made a small demo to show how we can declaratively fetch data and render it on screen by using the
useFetch
hook with the native Fetch API.If you are using Next.js, I highly recommend you to use SWR by Vercel instead of this custom hook.