How to fetch data with React Hooks
Tags: react, javascript, jsx
Published: 2021-03-30 18:19:09

---
title: How to fetch data with React Hooks
published: true
date: 2021-02-21 00:00:00 UTC
tags: react, javascript, jsx
canonical_url: https://www.mariokandut.com/how-to-fetch-data-with-react-hooks/
---

Short reminder what [React Hooks](https://www.mariokandut.com/how-to-use-react-hooks/) are, and here [useState](https://www.mariokandut.com/how-to-use-react-usestate-hook/) and [useEffect](https://www.mariokandut.com/how-to-use-useeffect-hook-in-react/) hooks in detail.

This blog article is about how to fetch data with React hooks or how to fetch data with useEffect.

[💰: Start your cloud journey with $100 in free credits with DigitalOcean!](https://m.do.co/c/29f238135b61)

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#useeffect)useEffect

The Effect Hook lets you perform side effects in function components. Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.

The **useEffect** Hook can be understood as **componentDidMount, componentDidUpdate, and componentWillUnmount combined** in the React class lifecycle methods.

Let's start with a "real" example. We want to fetch articles from [hackernews.com](https://www.hackernews.com) with a specific topic and display the resulting articles in a list with links to the corresponding article. HackerNews has a search API, which is powered by Algolia and it can be queried. As a query string you can use whatever you want, I will use `react`. The HackerNews API is public, free, and well documented, [Search Hacker News](https://hn.algolia.com/api).

We start with scaffolding our app with `Create React App` and then open `App.js`.

Delete all the boiler plate besides the import and the return. Your `App.js` should look like this:

```
import React from 'react';

function App() {
  return <div></div>;
}

export default App;
```

We need a state to store the result from the api.

```
import React, { useState } from 'react';

function App() {
  const [data, setData] = useState({ articles: [] });

  return <div></div>;
}

export default App;
```

When we look at the API we see the data structure for the returned article. We need the ObjectID, the title and the url properties and can already make the list.

```
import React, { useState } from 'react';

function App() {
  const [data, setData] = useState([]);

  return (
    <ul>
      {data.map(item => (
        <li key={item.ObjectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;
```

Now we need to fetch the data from the API with the useEffect hook.

```
import React, { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    // here goes the data fetching
  });

  return (
    <ul>
      {data.map(item => (
        <li key={item.id}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;
```

For fetching data we can use the `fetch` API or a third-party plugin like `axios`. I prefer the native fetch API.

The **useEffect hook can't be async** , so declare the async function inside the effect and then call it.

```
import React, { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch(
        'https://hn.algolia.com/api/v1/search?query=react',
      );
      const json = await res.json();
      setData(json.hits);
    };
    fetchData();
  });

  return (
    <ul>
      {data.map(item => (
        <li key={item.ObjectId}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;
```

Did you notice something? We are not passing the second argument to useEffect here. Don’t do this. This means `useEffect` runs on every render and could potentially cause an infinite loop. To fix this, we need to **pass an array as the second argument**. Have a look at the [how to use the useEffect hook](https://www.mariokandut.com/how-to-use-useeffect-hook-in-react/) article.

The only variable that useEffect depends on is setData. Hence, we should pass the array `[setData]` here. Because setData is a setter returned by useState, it won’t be recreated every render, and so the effect will only run once.

```
import React, { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch(
        'https://hn.algolia.com/api/v1/search?query=react',
      );
      const json = await res.json();
      setData(json.hits);
    };
    fetchData();
  }, [setData]);

  return (
    <ul>
      {data.map(item => (
        <li key={item.ObjectId}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;
```

That's it. We fetched data with the useEffect hook. Next steps would be a loading indicator and error handling. This will be covered in an upcoming post.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#tldr)TL;DR

- useEffect makes fetching data easier
- Always provide a cleanup function to useEffect, to avoid running on every render.
- useEffect can't be async, use an async function inside useEffect

Thanks for reading and if you have any **questions** , use the **comment** function or **send me a message** **[@mariokandut](https://www.twitter.com/mariokandut)**.

If you want to know more about **[React](https://www.mariokandut.com/tags/react)**, have a look at these [React Tutorials](https://www.mariokandut.com/tags/react).

References (and Big thanks):

[ReactJS](https://reactjs.org/docs/hooks-overview.html), [Dave Ceddia](https://daveceddia.com/useeffect-hook-examples/#useeffect-does-not-actively-watch), [Robin Wieruch](https://www.robinwieruch.de/react-hooks-fetch-data)