100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
React

Custom Hooks in React

Learn how to extract reusable stateful logic into your own custom hooks that follow the rules of hooks.

Advanced HooksIntermediate11 min readJul 8, 2026
Analogies

Introduction

A custom hook is simply a JavaScript function whose name starts with 'use' and that calls other hooks inside it. Custom hooks let you extract stateful logic — such as fetching data, subscribing to a browser event, or managing a form field — out of a component and into a reusable function that any component can call. Unlike regular helper functions, custom hooks can use useState, useEffect, useContext, and other hooks internally, and each component that calls a custom hook gets its own independent state.

🏏

Cricket analogy: Think of a custom hook like a fielding drill a coach designs, such as useSlipCatching, that any player can run through — Kohli and Rahane each practice it separately, keeping their own reps count and form, not a shared tally.

Syntax

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

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    function handleResize() {
      setWidth(window.innerWidth);
    }
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return width;
}

Explanation

A custom hook is created by writing a function named useSomething and moving hook calls (useState, useEffect, useContext, useRef, etc.) into it, then returning whatever the calling component needs — a value, a tuple of value and setter, or an object of related values and functions. Because it follows the naming convention 'use*', React's linter can verify it obeys the Rules of Hooks, and it can itself call other hooks. Crucially, calling a custom hook does not share state between components: each call site gets its own isolated useState/useEffect instances, just as if the logic had been written inline in that component. This makes custom hooks a mechanism for reusing logic, not for reusing state across components — that's what Context or a shared store is for. Good candidates for extraction are logic patterns repeated across multiple components, such as data fetching with loading/error states, subscribing to a browser API, debouncing a value, or managing a toggle.

🏏

Cricket analogy: Building useStrikeRotation bundles useState for runs and useEffect for over-tracking into one function named with 'use' so tooling flags misuse, returning strike-rate data — Dhoni's innings and Kohli's innings each stay untouched and separate.

Example

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

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    fetch(url)
      .then((res) => res.json())
      .then((json) => {
        if (!cancelled) {
          setData(json);
          setLoading(false);
        }
      })
      .catch((err) => {
        if (!cancelled) {
          setError(err);
          setLoading(false);
        }
      });
    return () => {
      cancelled = true;
    };
  }, [url]);

  return { data, loading, error };
}

function UserProfile({ userId }) {
  const { data, loading, error } = useFetch(`/api/users/${userId}`);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Something went wrong.</p>;
  return <h2>{data.name}</h2>;
}

Output

UserProfile shows 'Loading...' while the fetch request for the given userId is in flight, then renders the user's name once data arrives, or an error message if the request fails. If two different components both call useFetch with different URLs, each gets its own independent data, loading, and error state — the internal useState calls are not shared, only the logic pattern is reused.

🏏

Cricket analogy: Like a live scoreboard app showing 'Loading...' while fetching a player's stats, then displaying Kohli's average or an error if the API fails; a second widget fetching Bumrah's bowling stats via the same useFetch keeps its own separate loading and error flags.

Key Takeaways

  • A custom hook is a function starting with 'use' that calls other hooks internally to encapsulate reusable stateful logic.
  • Custom hooks must follow the Rules of Hooks, including being called at the top level, not inside loops or conditions.
  • Each component using a custom hook gets independent state; custom hooks share logic, not state, across components.
  • Good candidates for custom hooks include data fetching, event listeners, debouncing, and form field management.
  • Custom hooks compose naturally by calling useState, useEffect, useContext, useRef, or even other custom hooks inside them.

Practice what you learned

Was this page helpful?

Topics covered

#React#ReactJsStudyNotes#WebDevelopment#CustomHooksInReact#Custom#Hooks#Syntax#Explanation#StudyNotes#SkillVeris