Most of the applications we create today consume data from external sources through APIs. They fetch data from a server and display it in their UI.

Using React, you can create a custom hook to fetch data from an API. Given a URL, this hook will return an object containing the data and an optional error message. You can then use this hook in a component.

Creating a Custom React Hook

Begin by creating a new file called useFetch.js. In this file, create a function called useFetch() that accepts a URL string as a parameter.

        const useFetch = (url) => {
}

The hook should make the API call immediately after it's called. You can use the useEffect() hook for this.

For the actual API calls, use the fetch API. This API is a promise-based interface that allows you to make requests and receive responses over HTTP asynchronously.

In the useFetch() custom hook, add the following.

        import { useEffect, useState } from "react";
 
const useFetch = (url) => {
  const [data, setdata] = useState(null);
  const [loading, setloading] = useState(true);
  const [error, seterror] = useState("");
 
  useEffect(() => {
    fetch(url)
    .then((res) => res.json())
    .then((data) => {
        seterror(data.error)
        setdata(data.joke)
        setloading(false)
    })
  }, [url]);
 
  return { data, loading, error };
};
 
export default useFetch;

In this hook, you are first initializing the state of three values:

  • data: Holds the API response.
  • error: Holds an error message if an error occurs.
  • loading: Holds a boolean value that indicates whether it has fetched the API data. Initialize the loading state to true. Once the API returns data, set it to false.

The useEffect() hook takes the URL string as an argument. This is to ensure it runs each time the URL changes.

The useFetch() function will return an object containing the data, loading, and error values.

Using a React Custom Hook

To use the useFetch() custom hook you just created, begin by importing it:

        const useFetch = require("./useFetch")

Then use it as follows:

        const {data, loading, error} = useFetch(url)

To demonstrate, consider the following Jokes component:

        const Jokes = () => {
    const url = "<https://sv443.net/jokeapi/v2/joke/Programming?type=single>";
    const { data, loading, error } = useFetch(url);
 
    if (loading) return (
        <div>Loading...</div>
    )
 
    return (
      <div>
        {error && <div>{error}</div>}
        {data && <div>{<div>{data}</div>}</div>}
      </div>
    );
};
 
export default Jokes;

It calls the useFetch() hook with the URL to the jokes API and receives the data, loading, and error values.

To render the Jokes component, first check if Loading is true. If it is, display a “Loading…” statement otherwise render the data and error message if any.

Why Use Custom React Hooks?

Just as you used the useFetch() custom hook in this component, you can reuse it again in other components. That is the beauty of externalizing the logic in hooks instead of writing it in each component.

Hooks are a powerful feature of React that you can use to improve the modularity of your code.