Creating Custom Hooks

🛠️ Creating a Custom Hook

Creating a Custom Hook involves extracting reusable stateful logic from one or more React components into a separate function. A custom Hook behaves like any other Hook and can internally use built-in Hooks such as useState, useEffect, useReducer, and useContext.

Important

A custom Hook should encapsulate reusable logic, not reusable UI. Components remain responsible for rendering, while custom Hooks manage behavior and state.

🎯 Why Create Custom Hooks?

When multiple components share similar state management or side-effect logic, copying that code leads to duplication and makes maintenance harder. Creating a custom Hook centralizes the logic into a single reusable function.

  • Reuse stateful logic across components.
  • Reduce duplicated code.
  • Separate business logic from presentation.
  • Improve maintainability and readability.

📋 Steps to Create a Custom Hook

Identify Repeated Logic
Move the Logic into a New Function
Name the Function Starting with use
Use Built-in Hooks Inside the Function
Return the Required Values and Functions
Reuse the Hook in Multiple Components

💻 Example 1: Creating a Counter Hook

Creating useCounter

import { useState } from "react";

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

  function increment() {
    setCount(current => current + 1);
  }

  function decrement() {
    setCount(current => current - 1);
  }

  function reset() {
    setCount(initialValue);
  }

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

The custom Hook contains all the counter logic and exposes only the values and functions needed by consuming components.

💻 Example 2: Using the Custom Hook

Using useCounter

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

  return (
    <>
      <h2>{count}</h2>

      <button onClick={increment}>
        +
      </button>

      <button onClick={decrement}>
        -
      </button>

      <button onClick={reset}>
        Reset
      </button>
    </>
  );
}

The component becomes much smaller because all state management has been moved into the custom Hook.

💻 Example 3: Creating a Window Size Hook

Creating useWindowSize

import {
  useState,
  useEffect
} from "react";

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

  useEffect(() => {
    function handleResize() {
      setWidth(window.innerWidth);
    }

    window.addEventListener(
      "resize",
      handleResize
    );

    return () => {
      window.removeEventListener(
        "resize",
        handleResize
      );
    };
  }, []);

  return width;
}

This Hook hides the event listener logic so any component can easily access the current browser width.

💻 Example 4: Reusing the Hook

Using useWindowSize

function Layout() {
  const width = useWindowSize();

  return (
    <h2>
      Window Width: {width}px
    </h2>
  );
}

Multiple components can use the same custom Hook without duplicating the resize logic.

📁 Recommended Project Structure

src
hooks
useCounter.js
useWindowSize.js
useFetch.js
useLocalStorage.js

📊 Component Logic vs Custom Hook

Component LogicCustom Hook
Mixed with UI code.Separated from presentation.
Difficult to reuse.Easy to reuse.
Often duplicated.Written once and reused.
Components become larger.Components remain focused on rendering.

📅 Custom Hook Creation Process

🎯 Common Use Cases

Encapsulate API requests, loading states, and error handling inside reusable Hooks.

Reuse validation logic, input handling, and submission behavior across multiple forms.

Wrap browser APIs such as window size, online status, geolocation, or local storage.

Build reusable utilities such as counters, timers, toggles, and theme management.

⚠️ Common Mistakes

  • Creating a custom Hook for logic that is used only once.
  • Returning unnecessary values or functions.
  • Mixing rendering logic with Hook logic.
  • Violating the Rules of Hooks inside a custom Hook.

Warning

Each component that uses a custom Hook gets its own independent state. Custom Hooks share logic, not state.

✅ Best Practices

  • Extract only logic that is reused or logically grouped.
  • Keep each custom Hook focused on a single responsibility.
  • Name every custom Hook with the use prefix.
  • Return only the values and functions that consumers actually need.
  • Compose multiple small custom Hooks instead of building one large Hook whenever possible.

📚 Official Resource

Learn more about creating custom Hooks in the official React documentation at Reusing Logic with Custom Hooks.

Summary

Creating a custom Hook involves extracting reusable stateful logic into a function whose name starts with use. Custom Hooks make React applications cleaner, more reusable, and easier to maintain by separating business logic from UI components while following the Rules of Hooks.