How to Create a Custom useFetch Hook in React

How to Create a Custom useFetch Hook in React

Introduction

Custom hooks are reusable functions that contain logic and can be used in functional components. A useFetch hook is a reusable function in React that abstracts the process of fetching data from an API, provides an efficient way to manage HTTP requests and handles the loading and error states.

In this article, we'll walk through the process of creating a custom useFetch hook in React.

Let's dive in!

Creating a custom useFetch hook in React

After setting up your react project, go to the src directory and create a folder called hooks. In this folder, create a new file called useFetch.js which will contain the useFetch logic.

Here is the code below:

import { useState, useEffect } from 'react';

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
      fetch(url)
      .then(response => {
        if (!response.ok) { 
          // error coming back from server
          throw Error('could not fetch the data for that resource');
        } 
        return response.json();
      })
      .then(data => {
        setIsLoading(false);
        setData(data);
        setError(null);
      })
      .catch(err => {
        setIsLoading(false);
        setError(err.message);
      })
  }, [url])

  return { data, isLoading, error };
}

export default useFetch;

Code explanation

Firstly, import the necessary dependencies inside the useFetch.jsfile. We import the useState and useEffect hooks from the 'react' library.

We declare the useFetch custom hook which takes a url parameter, which represents the API endpoint we want to fetch data from.

We declare three state variables using the useState hook imported from the react library. The data state variable is the fetched data and is set to null. The isLoading state variable indicates whether the data is currently being fetched and is set to true. The error state variable represents errors that could occur during the data fetching process and it is initially set to null.

Next, we declare the useEffect hook which will be triggered whenever the url dependency changes. We define a fetch() function inside the useEffect callback and this function sends a GET request to the specified url. The then callback function is used to handle the response from the server.

We use response.ok to check for errors from the API and If an error is detected, an error message is thrown using the throw statement. And if there are no errors, the response is converted to JSON format using response.json(). We store the resulting data in the setData state variable, isLoading is set to false, and the error state variable is also set to null.

Next, we define a catch callback function to handle any errors that occurred during the fetch request. The isLoading state variable to false, indicating that the data loading has been completed and the error message is stored in the setError state variable.

Finally, the useFetch custom hook returns an object containing the data, isLoading, and error state variables for components to access these values. Then we export the useFetch custom hook as the default export of the module so it can be imported into other files.

How to use the useFetch Hook in a React component

To utilize the useFetch Hook, create the functional component and import the hook into your React component.

Code sample

import { useFetch } from '../hooks/useFetch'

const BlogPosts = () => {

    const { data: blogs, isLoading, error } = useFetch('http://localhost:3000/blogposts');

    return (
      <div>
        {isLoading && <div>Loading blog posts...</div>}
        {error && <div>{error}</div>}

       {/* Render the fetched data */}

        {blogs && blogs.map((blog) => (
          <p key={blog.id}>{blog.name}</p>
        ))}
      </div>
    );
  }

export default BlogPosts;

In the above component, we're using the useFetch hook to fetch data from the http://localhost:3000/blogposts endpoint. The data, isLoading, and error state variables returned by the hook are then used to conditionally render the content. If isLoading is true, then a loading message will be displayed, and If an error occurs, an error message will be displayed, otherwise the fetched data will be rendered in the component.

Lastly, import the functional component <BlogPosts /> inside the App component in the React project directory.

Conclusion

We have successfully created a useFetch Hook in React and utilize it in a functional component. A custom useFetch hook contains a data fetching logic which can be used across different components in a React project allowing us to write a clean and maintainable code.