How to trigger data fetching with React hooks?
Tags: react, javascript
Published: 2021-05-23 23:22:12

---
title: How to trigger data fetching with React hooks?
published: true
date: 2021-03-03 00:00:00 UTC
tags: react, javascript
canonical_url: https://www.mariokandut.com/how-to-trigger-data-fetching-with-react-hooks/
---

In many applications fetching data is done by triggering a React hook programmatically or manually. This article gives an example on how to do this. The used example is from the previous article [How to fetch data with react hooks](https://www.mariokandut.com/how-to-fetch-data-with-react-hooks/), below is the code:

```
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;
```

### [<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>](#fetch-data-programmatically-with-useeffect)Fetch data programmatically with useEffect

The above example fetches data when the component mounts. We are always fetching the exact same query "react". Let's add an input element to fetch other stories. Therefore, we have to add an input field, a state for the search query from the input field and update `fetchData` to use this dynamic search query.

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

function App() {
  const [data, setData] = useState([]);
  const [query, setQuery] = useState('react');

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

  return (
    <React.Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <ul>
        {data.map(item => (
          <li key={item.ObjectId}>
            <a href={item.url}>{item.title}</a>
          </li>
        ))}
      </ul>
    </React.Fragment>
  );
}

export default App;
```

One last thing. Try to update the code and run it. Did you notice something? When you type in the input field, the search is not triggering the `fetchData()`. The reason is that the useEffect hook does not depend on anything. The second argument of useEffect is an empty array, so it is only triggered once when the component mounts. The effect should run, when the search query changes. Hence, we have to provide the query as the second argument.

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

function App() {
  const [data, setData] = useState([]);
  const [query, setQuery] = useState('react');

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

  return (
    <React.Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <ul>
        {data.map(item => (
          <li key={item.ObjectId}>
            <a href={item.url}>{item.title}</a>
          </li>
        ))}
      </ul>
    </React.Fragment>
  );
}

export default App;
```

Now on every change of the input field data is fetched. What if we want to add a Search button to avoid fetching on every key stroke?

### [<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>](#fetch-data-manually-with-useeffect)Fetch data manually with useEffect

To avoid fetching data on every change of the query state, we can simply add a button to trigger `fetchData()`. Let's try it. We add a button with an `onClick` method to set a new state `search`, which triggers the useEffect hook.

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

function App() {
  const [data, setData] = useState([]);
  const [query, setQuery] = useState('react');
  const [search, setSearch] = useState('react');

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

  return (
    <React.Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button onClick={() => setSearch(query)}>Search</button>
      <ul>
        {data.map(item => (
          <li key={item.ObjectId}>
            <a href={item.url}>{item.title}</a>
          </li>
        ))}
      </ul>
    </React.Fragment>
  );
}

export default App;
```

Well, now it works. Somewhat. We have two states to manage the search query. We have to refactor the code to remove duplication. Instead of setting an additional search state, which is the same as the query state, we can just provide the url with the query to `fetch`.

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

function App() {
  const [data, setData] = useState([]);
  const [query, setQuery] = useState('react');
  const [url, setUrl] = useState(
    'https://hn.algolia.com/api/v1/search?query=react',
  );

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch(url);
      const json = await res.json();
      setData(json.hits);
    };
    fetchData();
  }, [search]);

  return (
    <React.Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button
        onClick={() =>
          setUrl(`https://hn.algolia.com/api/v1/search?query={query}`)
        }
      >
        Search
      </button>
      <ul>
        {data.map(item => (
          <li key={item.ObjectId}>
            <a href={item.url}>{item.title}</a>
          </li>
        ))}
      </ul>
    </React.Fragment>
  );
}

export default App;
```

That's if for the implicit programmatic data fetching with `useEffect`. You can decide on which state the effect depends. Once you set this state, the useEffect will run again. In this case, if the URL state changes, the effect runs again to fetch data from the API.

## [<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

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

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).

### [<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>](#references-and-big-thanks)References (and Big thanks):

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