React  

How to Create a Custom Hook in React With a Real World Example

Introduction

In modern React development, writing clean, reusable, and maintainable code is essential. As applications grow, you may notice repeated logic across components—such as fetching API data, handling forms, or managing window events. This is where Custom Hooks in React become extremely powerful.

Custom Hooks allow you to extract and reuse logic across multiple components, making your code cleaner and easier to scale. In this article, you will learn what custom hooks are, why they are important, and how to create one step-by-step using a real-world example.

This guide uses simple, practical language so beginners can follow along while still offering best practices for experienced developers.

What is a Custom Hook in React?

A Custom Hook is simply a JavaScript function that uses React hooks like useState, useEffect, or others to share reusable logic.

👉 Important Rule:

  • Custom Hook name must always start with "use"

Examples:

  • useFetchData

  • useForm

  • useWindowSize

Custom hooks do not change how React works—they just help you organize and reuse logic better.

Why Use Custom Hooks?

  1. Reusability

Instead of writing the same logic again and again, you can reuse it across components.

  1. Clean Code Structure

Components stay focused on UI, while logic moves into hooks.

  1. Better Readability

Your code becomes easier to understand and maintain.

  1. Scalability

As your app grows, custom hooks help manage complexity efficiently.

Real-World Problem Example

Imagine you are building a dashboard where multiple components need to fetch API data.

Without a custom hook:

  • Each component repeats fetch logic

  • Hard to maintain

  • More chances of bugs

Solution:
👉 Create a reusable custom hook for API fetching

Step-by-Step: Create a Custom Hook

Let’s build a custom hook called useFetch that fetches data from an API.

Step 1: Create a Custom Hook File

Create a new file:

// useFetch.js
import { useState, useEffect } from "react";

const 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("Failed to fetch data");
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
};

export default useFetch;

Explanation

  • useState → manages data, loading, and error

  • useEffect → runs API call when URL changes

  • return → exposes values to components

Step 2: Use Custom Hook in a Component

import React from "react";
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 (
    <div>
      <h2>User List</h2>
      <ul>
        {data.map((user) => (
          <li key={user.id}>
            {user.name} - {user.email}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default Users;

What Just Happened?

  • The component does not handle API logic anymore

  • It only focuses on displaying data

  • Logic is reusable across multiple components

Step 3: Reuse the Same Hook Anywhere

You can now reuse useFetch in different components:

const { data } = useFetch("https://jsonplaceholder.typicode.com/posts");

👉 Same logic, different API

Advanced Enhancement (Optional)

You can make your custom hook more powerful by adding:

  1. Refetch functionality

const refetch = () => {
  setLoading(true);
  setError(null);
  fetchData();
};
  1. Abort controller (to avoid memory leaks)

  2. Caching for better performance

Best Practices for Custom Hooks

  1. Always start with "use"

This ensures React recognizes it as a hook.

  1. Keep hooks focused

Each hook should solve one specific problem.

  1. Avoid UI logic inside hooks

Hooks should handle logic, not JSX.

  1. Use dependency arrays carefully

Incorrect dependencies can cause infinite loops.

  1. Handle cleanup properly

Especially for API calls and subscriptions.

Common Mistakes to Avoid

  • Not following naming convention (missing "use")

  • Overcomplicating hooks

  • Mixing UI with logic

  • Not handling errors

Real-World Use Cases of Custom Hooks

  • API data fetching (useFetch)

  • Form handling (useForm)

  • Authentication (useAuth)

  • Window resize tracking (useWindowSize)

  • Dark mode toggle (useTheme)

Conclusion

Custom Hooks are one of the most powerful features in React. They help you write cleaner, reusable, and scalable code by separating logic from UI.

By learning how to create and use custom hooks, you can significantly improve your React development workflow and build better applications.

Start by creating small hooks like useFetch, and gradually move toward more advanced patterns like shared state, caching, and custom logic abstraction.