DEV Community

Cover image for From Repetition to Reusability: Custom Hooks in React
Vinayagam
Vinayagam

Posted on

From Repetition to Reusability: Custom Hooks in React

Introduction

When I started learning React, everything looked simple. Creating components, using useState, and handling events felt easy. But as I started building more applications, I noticed one problem again and again β€” I was repeating the same logic in different components.

For example, fetching data, handling inputs, managing loading states β€” these things were written multiple times. At first, I ignored it. But later, the code became confusing and harder to maintain.

That is when I learned about Custom Hooks.


What is a Custom Hook?

A Custom Hook is a normal JavaScript function that starts with the word use. It allows us to reuse logic that involves React Hooks like useState and useEffect.

It is not a new feature with special syntax. It is just a pattern that React encourages.

In simple words, a Custom Hook helps us move repeated logic into one place and use it anywhere.


Why Custom Hooks are Useful

While building projects, we often write the same logic in different components. For example, fetching API data or handling form values.

Copying the same code again and again may look easy at first, but later it creates problems. If we want to update something, we need to change it in multiple places.

Custom Hooks solve this problem by keeping logic in one place. When we update the hook, it reflects everywhere.

This makes the code cleaner and easier to understand.


Basic Structure of a Custom Hook

Creating a Custom Hook is simple. It is just a function.

function useExample() {
  // logic here

  return value;
}
Enter fullscreen mode Exit fullscreen mode

The important rule is the function name must start with use.


Creating a Simple Custom Hook

Let’s create a small example to understand better.

useCounter Hook

import { useState } from "react";

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

  const increment = () => setCount(prev => prev + 1);
  const decrement = () => setCount(prev => prev - 1);

  return { count, increment, decrement };
}

export default useCounter;
Enter fullscreen mode Exit fullscreen mode

Using the Hook

import useCounter from "./useCounter";

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

  return (
    <div>
      <h2>{count}</h2>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here, I understood that the logic is completely separated from the UI. The component only displays the data.


Custom Hook for API Calls

Fetching data is something we do very often in React.

Instead of writing the same useEffect code everywhere, we can create a Custom Hook.

import { useState, useEffect } from "react";

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

  useEffect(() => {
    async function fetchData() {
      const res = await fetch(url);
      const result = await res.json();
      setData(result);
      setLoading(false);
    }

    fetchData();
  }, [url]);

  return { data, loading };
}

export default useFetch;
Enter fullscreen mode Exit fullscreen mode

Using the Hook

import useFetch from "./useFetch";

function Users() {
  const { data, loading } = useFetch(
    "https://jsonplaceholder.typicode.com/users"
  );

  if (loading) return <p>Loading...</p>;

  return (
    <div>
      {data.map(user => (
        <p key={user.id}>{user.name}</p>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

After using this, my components became much simpler.


Rules to Remember

While working with Custom Hooks, there are some important rules.

The function name must always start with use.
Hooks should not be used inside loops or conditions.
Hooks should only be used inside React components or other hooks.

Following these rules is very important to avoid errors.


When to Create a Custom Hook

One mistake I made in the beginning was trying to create hooks for everything.

But later I understood that Custom Hooks are useful only when logic is repeated or when a component becomes too large.

If something is used only once, it is okay to keep it inside the component.


Real-Time Use Cases

In real projects, Custom Hooks are used in many situations.

For example:

Handling authentication logic
Managing form inputs
Working with local storage
Tracking window size
Handling dark mode

Once you start building real applications, you will see these patterns everywhere.


Common Mistakes Beginners Make

One common mistake is returning JSX from a hook. Hooks should not return UI.

Another mistake is creating very large hooks that handle too many things. This makes them difficult to understand.

Also, forgetting dependency arrays in useEffect can cause unexpected behavior.

I personally faced these issues when I started, so it is important to practice carefully.


How Custom Hooks Improve Code

Before using Custom Hooks, my components had too much logic inside them. It was difficult to read and understand.

After using hooks, I started separating logic into different files. This made the project more organized.

Now I usually create a hooks folder and store all reusable logic there.


Final Thoughts

Custom Hooks may look simple, but they are very powerful. They help us write better React code by keeping logic reusable and components clean.

The best way to learn Custom Hooks is by practicing. Whenever you see repeated logic, try to convert it into a hook.

That small habit will slowly improve your coding style.

Top comments (0)