Better Programming

Advice for programmers.

Follow publication

How to Build a Custom React Hook for Fetching Data

Miroslav Pillár
Better Programming
Published in
3 min readApr 9, 2020

Photo by Twixes on Unsplash

I’m sure you’ve heard the hype around React Hooks. There’s no need to give you the basics — the internet is full of this. Also, if you’re interested in building custom Hooks, you probably already know a bit about them.

So let’s get right to the code.

Sample Code for Getting Data

Most web apps use some sort of API for getting data. First, we’re going to create a sample code.

Let’s use the component UserList.js, where we want to fetch users after the page is mounted to the view. For demonstration purposes, I’ll use the fake API JSONplaceholder.

The component’s basics will look like this:

UserList.js

We’re going to save data in state users which is handled by useState Hook. During fetching, we’ll show a loading message to give a better user experience.

Data Fetching

In React 16.8 and higher, this is done with the useEffect Hook:

  • First, we set loading to true.
  • The whole code block for getting the data is called as soon as it’s defined (lines 6 and 18). This quirk is called an “Immediately Invoked Function Expression” (or IIFE).
  • I’m using async-await instead of a traditional Promise based approach. For proper handling of errors, I’ve implemented try-catch-finally blocks.
  • In this case, Fetch API is used, but you can use Axios as well.

Performance Optimization

You should always keep the performance aspects of your code in mind.

To prevent from fetching data on unmounted component, we can use another Hook, useRef. The purpose is that it should run code within useEffect only if the component is mounted to the view. Otherwise, you might get this familiar (to React developers) warning:

Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

Here’s the final version of useEffect:

On line four we first check whether the component is mounted. If yes, we try to fetch the data. It’s also important to set the current reference to false in the cleanup function (lines 26–28).

Creating a Reusable Custom Hook

Our useEffect has grown into a lot of codes, which could pollute the component’s environment. If you fetch data in several components inside the project, you’re also breaking the DRY (Don’t Repeat Yourself) principle .

Implementing built-in hooks from React

Let’s create a new file useFetch.js with the following code:

  • useFetch is just a special type of function, which will include built-in hooks from React.
  • It accepts parameters — URL, reference and initial value for the state.
  • This hook will store data, error, and loading in states accordingly (lines 4–6).

Now the only thing we’re still missing is data fetching itself. We can do that in useEffect, as above:

This custom Hook must return states we defined. We can do it by using object destructuring on line 26.

Back to our component

Now we’re ready to use the custom Hook inside the component. Remove unnecessary code and store results of the Hook in variables:

In useFetch(), we’re passing URL for fetching users, isComponentMounted as a reference, and empty array as the initial value for data.

Now our users will be stored in data and the component will re-render as soon as data is fetched or an error occurs. You can handle errors within the component according to your needs.

How to test it?

So you just created a reusable custom Hook, which you can use across all React projects. But is it really reliable?

To find it out, you should write some unit tests. Feel free to continue reading my next article about this topic:

Thanks for reading!

Sign up to discover human stories that deepen your understanding of the world.

Miroslav Pillár
Miroslav Pillár

Written by Miroslav Pillár

A self-studied web developer with a passion for writing about Frontend, Javascript and its related content.

Write a response