Hello Guys,
In this post, I will explain how to create a custom hook which will fetch data and how can we reuse it in different components.
React hooks are relatively new compared to class components. If you are new to hooks, I will strongly recommend to go through the official documentation. Here is the link hooks.
Hope you have an idea about hook.So let's start.
const useFetch = (url, options) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const resp= await fetch(url, options);
const data = await resp.json();
setData(data);
} catch (e) {
setData([]);
setError(e);
}
}
fetchData();
}, []);
return { data, error }
}
Let me explain what I have done here.
I have created a custom hook useFetch which is basically a function which takes in two arguments(url and options) and it returns an object with state(data, error).
I have used two react hooks(useState and useEffect).
useState is a hook that allows you to have state variables in functional components.
useEffect is a hook that allows to have side effects from within functional components(updating DOM, making asynchronous call..). It accepts two arguments, first one is the callback and second one is the dependencies array. Anytime if any of the dependency in the dependencies array changes, the callback is fired.
In our case useEffect has no dependencies. So that means our callback function will be called only once(you can imagine how componentDidMount works in a class component). Inside the callback, we have fetchData which is a async function, which actually does a fetch call with the url and options.
We can extend this to have a loading state. Let me add the loading state into our hook.
const useFetch = (url, options) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const resp= await fetch(url, options);
const data = await resp.json();
setData(data);
} catch (e) {
setData([]);
setError(e);
}
setIsLoading(false);
}
fetchData();
}, []);
return { data, error, isLoading }
}
Now then we have added the loading state, let's see how we can consume this hook in different components.
Let's assume we have a component Component1.js and I want to consume the custom hook that we just created.
const Component1 = () => {
const { data, error, isLoading } = useFetch('someUrl', { method: 'get'});
if (isLoading ) {
//Show a loader here because fetch is still going on.
// return <Loader />
}
if (error) {
// Show some error message
// return <ErrorState />
}
return (
// Do something with data
)
}
I can consume the custom hook in different other components.That means I can reuse the state(data, error, isLoading) in other components too and that was the main idea behind hooks(Reuse state).
Hooks are really great addition to the react. We can make use of react features without writing class components.
That's it for this article. I hope this helped you.
Leave any feedback, suggestion, question if you have and most importantly keep learning.
Top comments (6)
const { data, error, isLoading } = useFetch('someUrl', { method: 'get'});
How can I append list (the data)? like concating with other list for infinite scrolling n all.
Would really like to know
Thanks
Very nice explanation!
I have just one question though, can we use this custom hook with some authentication token or something, probably the one that should be included in the dependency array? Can you give us an example? Thank you!
So without reading the full article on hooks and looking them up: can it be said that hooks are constructed similar to promises in that our first parameter acts as it's "resolve," and it's second param as it's "reject?"
Not exactly. In this article I just tried to demonstrate how we can make use of react hooks to our advantage. This is one of the scenarios where I just created a custom hook and how we can use them in different components.
Custom hook does not necessarily have to fetch data. You can use them as per your use case. Hope I made it clear.
For your useEffect. You have to put “url“ and “options“ to dependencies array.
You can put them in the dependencies array. No problem. That becomes a different scenario meaning every time url or options change, callback is fired. In my case I want the callback to be fired only once. So the dependencies array empty. You can imagine how componentDidMount works in a class component. It gets called only once after the initial rendering.