DEV Community

loading...
Cover image for React custom hook to fetch data

React custom hook to fetch data

abhmohan
Web Developer
・2 min read

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 }
} 
Enter fullscreen mode Exit fullscreen mode

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 }
} 
Enter fullscreen mode Exit fullscreen mode

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
    )
} 
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (5)

Collapse
vnankov profile image
Valentin Nankov

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!

Collapse
eissorcercode99 profile image
The EisSorcer

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?"

Collapse
abhmohan profile image
abhmohan Author

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.

Collapse
mykhailo profile image
Mykhailo Onikiienko • Edited

For your useEffect. You have to put “url“ and “options“ to dependencies array.

Collapse
abhmohan profile image
abhmohan Author

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.