Back to all posts

Building Custom Hooks in React


React hooks have become an integral part of React development, providing a way to use state and other React features without writing a class, Custom hooks are a powerful feature that allow you to extract component logic into reusable functions.

Understanding React Hooks

Before we dive into creating custom hooks, it’s important to understand what are in React.

A hooks is a function that lets you “hook into” React state and lifecycle features from function components. Hooks don’t work inside classes they let you use React without classes. Hooks are new addition in React 16.8. They let you use state and other React features without writing a class.

Rules for Using React Hooks

In React, a custom Hook is a function that starts with the word “use” and may call other Hooks. The general rules of React Hooks also apply to custom Hooks. These include:

  • Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.
  • There is only one other valid place to call Hooks, your own custom Hooks. These rules are in place because React relies on the order in which Hooks are called to associate the Hooks with a certain local state. Placing a Hook inside conditions may change this order, resulting in the subsequent Hooks failing to be called, and more likely than not, resulting in bugs.

Creating a Custom Hook

Let’s create a custom hook that fetches data from an API. This is a common use case for a custom hook.

First, we’ll create a new file for our custom hook. This is a good practice as it helps to keep our codebase organized. Let’s call this file useFetch.js.

// useFetch.js
import { useState, useEffect } from 'react';

function useFetch(url) {
 const [data, setData] = useState(null);
 const [loading, setLoading] = useState(true);
 const [error, setError] = useState(null);

 useEffect(() => {
   async function fetchData() {
     try {
       const response = await fetch(url);
       const data = await response.json();
       setData(data);
       setLoading(false);
     } catch (error) {
       setError(error);
       setLoading(false);
     }
   }
   fetchData();
 }, [url]);

 return { data, loading, error };
}

export default useFetch;

In the useFetch hook, we’re using the useState hook to create a state variable for the data, loading status, and error. We’re also using the useEffect hook to fetch the data when the component mounts. The fetchData function is asynchronous, meaning it returns a Promise that resolves to the data we want.

The useFetch hook returns an object with the data, loading status, and error, which we can then use in our components

Using the Custom Hook

ow that we’ve created our custom hook, we can use it in our components. Here’s an example of how we might use the useFetch hook in a component:

// App.js
import React from 'react';
import useFetch from './useFetch';

function App() {
 const { data, loading, error } = useFetch('https://api.example.com/data');

 if (loading) return <div>Loading...</div>;
 if (error) return <div>Error: {error.message}</div>;

 return (
   <div>
     {data.map(item => (
       <div key={item.id}>{item.name}</div>
     ))}
   </div>
 );
}

export default App;

In this example, we’re passing the URL of the API we want to fetch data from to the useFetch hook. The hook returns an object with the data, loading status, and error, which we then use to render different UI based on the state of the data fetching

Please check this codesanbox

check useFetch.js file