How to Load Data from a REST API with React Hooks

With this week’s release of React 16.8, Hooks were finally released into the wild. They allow us doing a lot of stuff that wasn’t possible until now. For example, loading data into the state of a functional component. But let’s have a closer look.

In a recent post, I wrote about loading data from a REST API into a React component by using the componentDidMount lifecycle method. That was the only recommended way to load data when a certain component has finished mounting.

And because it was the only way, we had to rewrite a functional component to a class component a lot. All of that just because we needed a little state or a lifecycle method … but no longer:

Hooks to the Rescue

With React Hooks there is another way to get data into your app. Finally we can have stateful logic in functional components – which allows us to have functional components as “containers”. If we now want a component to load data at mount, we don’t need a class component anymore. At least not just because we need state or lifecycle. Two Hooks make that possible: useState allows us to add state functionality to our component. and useEffect gives us the possibility to perform so called side effects like fetching data asynchronously.

Here’s a very basic example of a component that loads and displays a list of users from a REST API. Similar to the example in my recent post:

import React, { useEffect, useState } from "react";
import axios from "axios";

export default function RestApiHooksComponent() {
const [data, setData] = useState([]);

useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(result => setData(result.data));
}, []);

return (
<div>
<ul>
{data.map(item => (
<li key={item.username}>
{item.username}: {item.name}
</li>
))}
</ul>
</div>
);
}

The useState Hook

Now let’s have a look at what happens here:

const [data, setData] = useState([]);

useState uses array destructuring to provide the current value of a state (we called it data) and a function to set a new state value (setData). The argument that we pass to useState is the initial value for data in the component’s state. You can imagine the state of the component is now looking like that:

{
data: []
}

So now we have a state in our component. But how do we get the data from our REST API into that field? That’s where we need useEffect:

The useEffect Hook

  useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(result => setData(result.data));
}, []);

At each render, useEffect executes the function we pass as the first argument. We don’t want to load the users each time the component re-renders, so we pass an empty array as second argument.

The second argument of useEffect allows us to pass dependencies to the Hook. For example, a value in state or a filter string that we could pass to our API. Each time one of those dependencies changes, useEffect will be executed again. Since we only want to fetch data once, we pass an empty array.

Inside the Promise that we get from axios we then update the state of our component with the freshly fetched data.

Wrapping Up

We should not go and rewrite our whole codebase to use Hooks and get rid of all class components. But I think it’s a great tool to make our codebase a lot cleaner.

It is totally fine to use Hooks and class Components in your codebase. So the next time you have to fetch some data when mounting, think of using Hooks in a functional component.

Did you already try hooks? Tell me in the comments about your experiences!

Improve your React Skills!

Learn about React concepts, helpful libraries or get tips & tricks for deploying your app and many more topics.

I semi regularly post about React. Don't miss out on my future posts! Sign up below to get them delivered directly into your inbox!

Leave a Reply

Your email address will not be published. Required fields are marked *