React Custom Hooks

Create reusable React Hooks that keep shared logic organized across components.

Custom Hooks in React

As React applications grow, developers often find themselves writing the same logic in multiple components. For example, several pages may need to fetch data from an API, track the browser window size, or manage form input. Writing the same code repeatedly makes the project harder to maintain.

React provides Custom Hooks to solve this problem. A custom Hook lets you move reusable logic into a separate function and use it wherever needed.

Custom Hooks help keep your components clean, organized, and easier to understand.

What is a Custom Hook?

A Custom Hook is a JavaScript function that uses one or more React Hooks, such as useState or useEffect, to provide reusable functionality.

Like built-in Hooks, every custom Hook must start with the word use.

Examples:

  • useFetch
  • useWindowSize
  • useTheme
  • useCounter

The use prefix tells React that the function follows the Rules of Hooks.

Why Do We Need Custom Hooks?

Imagine you have three different pages that all load product data from an API.

Without a custom Hook, each page would contain the same code for:

  • Creating state
  • Loading data
  • Handling errors
  • Displaying loading messages

This leads to duplicate code.

With a custom Hook, you write the logic once and reuse it in every component.

Benefits of Custom Hooks

  • Reuse code easily
  • Reduce duplication
  • Keep components clean
  • Improve readability
  • Simplify maintenance
  • Make testing easier

Creating Your First Custom Hook

Here is a simple custom Hook that manages a counter.

useCounter.js

JSX
import { useState } from "react";

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

  function increase() {
    setCount(count + 1);
  }

  return { count, increase };
}

export default useCounter;

Explanation

  • useCounter() is a custom Hook.
  • It stores a counter using useState.
  • It returns both the current value and a function to update it.

Using the Custom Hook

Now the Hook can be used inside any React component.

JSX
import useCounter from "./useCounter";

function App() {
  const { count, increase } = useCounter();

  return (
    <button onClick={increase}>
      Count: {count}
    </button>
  );
}

Output

devbrainbox.local/output
Count: 0
Count: 1
Count: 2
...

The component stays small because the counter logic is stored in the custom Hook.

Custom Hook for API Requests

Custom Hooks are commonly used to fetch data from APIs.

JSX
import { useState, useEffect } from "react";

function useUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://example.com/api/users")
      .then((response) => response.json())
      .then((data) => setUsers(data));
  }, []);

  return users;
}

Now, any component that needs user data can simply call:

JSX
const users = useUsers();

Instead of rewriting the same API code, you reuse the custom Hook.

Rules for Custom Hooks

Custom Hooks follow the same rules as built-in Hooks.

  • Always start the name with use.
  • Call Hooks only at the top level.
  • Do not call Hooks inside loops or conditions.
  • Use custom Hooks only inside React components or other custom Hooks.

Following these rules ensures React works correctly.

When Should You Create a Custom Hook?

Create a custom Hook when:

  • The same logic is repeated in multiple components.
  • You want to organize complex code.
  • You want to separate business logic from the user interface.
  • Multiple components need the same functionality.

If the logic is only used once, keeping it inside the component may be simpler.

Best Practices

When creating custom Hooks:

  • Give the Hook a meaningful name.
  • Keep each Hook focused on one responsibility.
  • Return only the data and functions that components need.
  • Avoid making Hooks overly complex.
  • Reuse Hooks whenever possible.
  • Store custom Hooks in a dedicated hooks folder.

Example project structure:

devbrainbox.local/output
src/
|
├── hooks/
|   ├── useCounter.js
|   ├── useUsers.js
|   └── useTheme.js
|
├── components/
└── App.jsx

This structure makes Hooks easy to find and reuse.