Menu

Building Custom Hooks

Building Custom Hooks

What is a Custom Hook?

A custom Hook is your own function that starts with use and calls other Hooks inside it. It lets you extract reusable logic out of components.

It is not a new React feature it is just a function. But the use prefix tells React (and the linter) to apply the Rules of Hooks to it.

Why is it Used?

Suppose three different components each need to fetch data, track loading, and handle errors. Without a custom Hook, that is the same twenty lines written three times.

Example

src/hooks/useFetch.jsx

jsx

import { useState, useEffect } from "react";

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

  useEffect(() => {
    let ignore = false;

    async function fetchData() {
      setLoading(true);
      setError(null);

      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`Request failed with status ${response.status}`);
        }
        const result = await response.json();
        if (!ignore) {
          setData(result);
        }
      } catch (err) {
        if (!ignore) {
          setError(err.message);
        }
      } finally {
        if (!ignore) {
          setLoading(false);
        }
      }
    }

    fetchData();

    return () => {
      ignore = true;
    };
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Using it in a component

jsx

import useFetch from "../hooks/useFetch";

function CourseList() {
  const { data: courses, loading, error } = useFetch("https://api.example.com/courses");

  if (loading) return <p>Loading courses...</p>;
  if (error) return <p className="error">{error}</p>;

  return (
    <ul>
      {courses.map(course => (
        <li key={course.id}>{course.title}</li>
      ))}
    </ul>
  );
}

How It Works

  • The Hook holds its own state and effect, exactly like a component would.
  • It returns an object, which the component destructures. data: courses renames data to courses while destructuring.
  • The ignore flag prevents setting state after the component has been removed, or after url changes mid-request. This avoids a common warning and a subtle race condition.
  • [url] as the dependency means changing the URL automatically refetches.

Each component that calls useFetch gets its own independent state. Custom Hooks share logic, not data.

A Simpler Custom Hook

Not every custom Hook needs to be complex:

jsx

import { useState } from "react";

function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);
  const toggle = () => setValue(prev => !prev);
  return [value, toggle];
}

// Usage
const [isMenuOpen, toggleMenu] = useToggle();

ReactJS Tutorial

VA

Vishalini A



Learn via Video Course

React.js for Beginners: Build Modern Web Applications with React Logo

React.js for Beginners: Build Modern Web Applications with React

6 hrs



Get in Touch For Details