Open In App

React Custom Hooks

Last Updated : 19 Aug, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

A custom hook is a JavaScript function that starts with use and internally calls other hooks like useState, useEffect, or useContext. It allows developers to extract reusable logic, keeping components clean and modular.

Syntax

function useCustomHook() {
// Use built-in hooks here
return someValue;
}

Steps to Create a Custom Hook

1. Define a Function That Starts with use

Custom hooks must follow React's naming convention and start with use (e.g., useFetch). This ensures React recognizes it as a hook and enforces hook rules.

function useCustomHook() {
// Hook logic here
return someValue;
}

2. Use React's Built-in Hooks Inside Your Custom Hook

Custom hooks can use useState, useEffect, useContext, etc., to manage state, handle side effects, or access context.

function useCounter() {
const [count, setCount] = useState(0);
return [count, () => setCount(count + 1)];
}

3. Add Logic Inside useEffect for Side Effects

If your custom hook performs side effects (e.g., fetching data, subscribing to a service), use useEffect to control when the effect runs.

function useFetchData(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url).then(response => response.json()).then(setData);
}, [url]);
return data;
}

4. Return Necessary Values

Your custom hook should return state, functions, or values that components need, such as fetched data, loading state, or error messages.

function useToggle(initialValue = false) {
const [state, setState] = useState(initialValue);
const toggle = () => setState(prev => !prev);
return [state, toggle];
}

5. Use the Custom Hook in Components

Once defined, your custom hook can be used inside a React component just like a built-in hook.

function ExampleComponent() {
const [isOn, toggle] = useToggle();
return <button onClick={toggle}>{isOn ? "ON" : "OFF"}</button>;
}

Implementing A Custom Hook

1. Creating a Custom Hook for Fetching Data

Custom hooks can be used for handling the API requests.

JavaScript
import { useState, useEffect } from 'react';

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

    useEffect(() => {
        fetch(url)
            .then((response) => response.json())
            .then((data) => {
                setData(data);
                setLoading(false);
            });
    }, [url]);

    return { data, loading };
}
function DataComponent() {
    const { data, loading } = useFetch("https://jsonplaceholder.typicode.com/todos/1");

    return (
        <div>
            {loading ? <p>Loading...</p> : <p>Data: {JSON.stringify(data)}</p>}
        </div>
    );
}

export default DataComponent;

Output

Animationkk
Creating a Custom Hook for Fetching Data

In this example

  • useFetch is the custom hook.
  • useFetch encapsulates API-fetching logic, making it reusable.
  • Components using useFetch don't have to implement fetching logic themselves.

2. Creating a Custom Hook for the Save Button with Online/Offline Status

This example consists of a custom hook (useOnlineStatus) that tracks the online/offline status of a user and a React component (SaveButton) that uses this custom hook to enable or disable a button based on the network status.

JavaScript
//src/App.js
import useOnlineStatus from './useOnlineStatus';

export default function SaveButton() {
    const isOnline = useOnlineStatus();

    function handleSaveClick() {
        console.log('✅ Progress saved');
    }

    return (
        <button disabled={!isOnline} onClick={handleSaveClick}>
            {isOnline ? 'Save progress' : 'Reconnecting...'}
        </button>
    );
}
JavaScript
//src/useOnlineStatus.js
import { useState, useEffect } from 'react';

function useOnlineStatus() {
    const [isOnline, setIsOnline] = useState(navigator.onLine);

    useEffect(() => {
        function handleOnline() {
            setIsOnline(true);
        }
        function handleOffline() {
            setIsOnline(false);
        }

        window.addEventListener('online', handleOnline);
        window.addEventListener('offline', handleOffline);

        return () => {
            window.removeEventListener('online', handleOnline);
            window.removeEventListener('offline', handleOffline);
        };
    }, []);

    return isOnline;
}

export default useOnlineStatus;

Output

In this example

  • useOnlineStatus hook tracks the user's internet connection status using useState and useEffect. It listens for online and offline events and updates the state accordingly.
  • This component imports the useOnlineStatus hook to determine whether the user is online. If offline, the button is disabled and displays "Reconnecting...". If online, the button is enabled with "Save progress."
  • The useEffect inside the custom hook adds event listeners for network status changes and cleans them up when the component unmounts to prevent memory leaks.
  • useOnlineStatus is a custom hook because it encapsulates the logic for checking internet status and can be reused across multiple components.

When to Use Custom Hooks

You should use custom hooks when

  • We need to reuse logic across multiple components.
  • We want to improve readability and maintainability by keeping component logic clean.
  • We are using multiple built-in hooks together in a reusable way.
  • We want to encapsulate side effects like data fetching or state management

Article Tags :