Fetching data with React hooks and Axios
Alessio Michelini
Posted on September 9, 2021
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;
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;
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;
I hope it will help you understanding better React hooks with this practical example.
Posted on September 9, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.