React custom hook to fetch data
Tags: react, javascript
Published: 2021-05-21 13:48:18

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](https://reactjs.org/docs/hooks-intro.html).

Hope you have an idea about hook.So let's start.

```javascript
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.

```javascript
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.

```javascript
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.