Hey, this is me Ashik Chapagain here.
Introduction
Whenever we need to fetch the data from API in React we use fetch
inside useEffect
and repeat the same in every component.
Like this.
import React from 'react';
import { useEffect, useState } from 'react';
export default function HomePage() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const json = await res.json();
setData(json);
};
fetchData();
}, []);
return (
<div>
{data &&
data.map(post => (
<div style={{ marginBottom: '20px' }}>{post.title}</div>
))}
</div>
);
}
But, But, But. ✋✋ Do you know you can do the same task more efficiently using a custom react hook?
import React from 'react';
import useFetch from '../hooks/useFetch.js';
export default function HomePage() {
const { loading, error, data } = useFetch(
'https://jsonplaceholder.typicode.com/posts'
);
if (loading) return 'Loading...';
if (error) return 'Error Occured';
return (
<div>
{data.map(post => (
<div style={{ marginBottom: '20px' }}>{post.title}</div>
))}
</div>
);
}
Look at the difference, we have loading
and error
too in the second example.
Let's Build
Create a new folder hooks
in the root directory and touch useFetch.js
.
Add the following content to useFetch.js
import { useEffect, useState } from 'react';
const useFetch = url => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const res = await fetch(url);
const json = await res.json();
setData(json);
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
};
fetchData();
}, [url]);
return { loading, error, data };
};
export default useFetch;
Now use it wherever it's needed.
How to use it?
import React from 'react';
import useFetch from '../hooks/useFetch.js';
export default function HomePage() {
const { loading, error, data } = useFetch(
'https://jsonplaceholder.typicode.com/posts'
);
if (loading) return 'Loading...';
if (error) return 'Error Occured';
return (
<div>
{data.map(post => (
<div style={{ marginBottom: '20px' }}>{post.title}</div>
))}
</div>
);
}
Thanks for reading this article.
Let's connect on:
- Twitter: https://twitter.com/ChapagainAshik
If you like this article, don't forget to react to this article.