React provides many built-in hooks like useState, useEffect, and useContext. Sometimes the same logic is repeated across components — for example, fetching data, handling forms, or working with localStorage. Custom hooks remove duplication and make your code easier to test and maintain.

Instead of repeating that logic, React lets you create your own hooks — called Custom Hooks.

React Custom Hooks are a way to extract and reuse stateful logic in React components. They allow you to create reusable logic that can be shared across multiple components without changing their structure.


useCounter using Custom

The useCounter hook is a simple example of a custom hook that manages a counter state. It provides an interface to increment, decrement, and reset the counter value.

Here's how you can implement the useCounter hook:


import { useState } from "react";

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);
  const reset = () => setCount(initialValue);

  return { count, increment, decrement, reset };
}

export default useCounter;


          import useCounter from "./useCounter";

function Counter() {
  const { count, increment, decrement, reset } = useCounter(5);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

use fetch api for data fetching

Custom hooks allow you to extract component logic into reusable functions. This is particularly useful for sharing logic between components without repeating code. For example, you might have multiple components that need to fetch data from an API. Instead of duplicating the fetch logic in each component, you can create a custom hook.

  1. Starts with the word “use” (example: useFetch, useLocalStorage)
  2. Can use other React hooks inside it (like useState, useEffect)

Here's an example of a custom hook that fetches data from an API:


import { useState, useEffect } from "react";

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

     useEffect(() => {
          const fetchData = async () => {
               try {
                    const response = await fetch(url);
                    if (!response.ok) {
                         throw new Error("Network response error");
                    }
                    const result = await response.json();
                    setData(result);
               } catch (error) {
                    setError(error);
               } finally {
                    setLoading(false);
               }
          };
          fetchData();
     }, [url]);

     return { data, loading, error };
}

Using a custom hook

You can use the useFetch hook in any component to fetch data from an API. Here's an example:


import useFetch from "./useFetch";

function Users() {
  const { data, loading, error } = useFetch("https://jsonplaceholder.typicode.com/users");

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

  return (
    <ul>
      {data.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

In this example, we created a custom hook called useFetch that fetches data from a given URL. It manages the loading state, error handling, and data storage internally. You can use this hook in any component to fetch data without duplicating the logic.


Rules for Creating Custom Hooks

  1. Custom hooks must start with the word "use".
  2. They can use other hooks (e.g., useState, useEffect).
  3. Custom hooks should be reusable and not tied to a specific component.
  4. They can accept parameters to customize their behavior.
  5. Custom hooks share logic — not UI.
  6. Don't call hooks inside loops, conditions, or nested functions.