Fetching data with React hooks and Axios

darkmavis1980

Alessio Michelini

Posted on September 9, 2021

Fetching data with React hooks and Axios

I have to be honest that I was getting a bit rusty with React lately, I've been working on mostly backend and CLIs stuff for the past few months, and as I have a very bad memory I tend to forget how things, I used not so long ago, works.

As now I have to work on the front facing part of the application, I need to fetch information from the API and display them, a solution could be to run something like this:

// mycomponent.js
import React, { useEffect, useState} from 'react';
import axios from 'axios';

const MyComponent = () => {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([])

  useEffect(() => {
    const fetchData = async () =>{
      setLoading(true);
      try {
        const {data: response} = await axios.get('/stuff/to/fetch');
        setData(response);
      } catch (error) {
        console.error(error.message);
      }
      setLoading(false);
    }

    fetchData();
  }, []);

  return (
    <div>
    {loading && <div>Loading</div>}
    {!loading && (
      <div>
        <h2>Doing stuff with data</h2>
        {data.map(item => (<span>{item.name}</span>))}
      </div>
    )}
    </div>
  )
}

export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

So essentially we tell the component that when it mounts, it should call the fetchData function to populate our data array from the API, and we put some conditions to not show anything while we area loading our data.

The code above is fine as it is, but it stores a bit of logic in the component itself.

If you need to reuse the same logic in another component, that perhaps renders the same data but in a different way, you need to duplicate it, making the code not very DRY.

Custom hooks FTW

I firmly believe that abstraction is always a good way to go, and in my opinion a better solution is to create a custom react hook, where essentially we move the logic of fetching the data to another file, and we make it a reusable hook that can be called from multiple components if needed.

The code for the hook will be something like this:

// use-fetch-data.js
import { useEffect, useState} from 'react';
import axios from 'axios';

const useFetchData = () => {
  const [data, setData] = useState({});
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const { data: response } = await axios.get('/stuff/to/fetch');
        setData(response);
      } catch (error) {
        console.error(error)
      }
      setLoading(false);
    };

    fetchData();
  }, []);

  return {
    data,
    loading,
  };
};

export default useFetchData;
Enter fullscreen mode Exit fullscreen mode

Note: for the sake of keeping the code short I didn't manage the state for errors, relying just on console.error.

Now we can refactor our component code, removing all the logic and the states we no longer need, to a much shorter code:

//mycomponent.js
import React from 'react';
import useFetchData from './hooks/use-fetch-data.js'

const MyComponent = () => {
  const {
    data,
    loading,
  } = useFetchData();

  return (
    <div>
    {loading && <div>Loading</div>}
    {!loading && (
      <div>
        <h2>Doing stuff with data</h2>
        {data.map(item => (<span>{item.name}</span>))}
      </div>
    )}
    </div>
  )
}

export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

I hope it will help you understanding better React hooks with this practical example.

💖 💪 🙅 🚩
darkmavis1980
Alessio Michelini

Posted on September 9, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related