Clue Mediator

Top 8 Custom Hooks Every React Developer Should Know About

📅February 6, 2025

So you've been working with React for a while, and you're ready to enhance your code efficiency, right? Let's chat about some awesome custom react hooks that can streamline your React projects and make your life easier!

Must-Know Custom Hooks for React

  1. usePrevious Hook
  2. useToggle Hook
  3. useDebounce Hook
  4. useOnClickOutside Hook
  5. useInterval Hook
  6. useLocalStorage Hook
  7. useWindowSize Hook
  8. useFetch Hook

1. usePrevious Hook

Ever needed to keep track of the previous value of a prop or state? The usePrevious hook is your friend! It’s super simple and returns the previous value of a prop or state to track changes over time. For instance, navigating through a photo gallery might require this to check which photo was viewed before.

import { useRef, useEffect } from "react";

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

Usage:

const previousCount = usePrevious(count);

2. useToggle Hook

The useToggle hook makes toggling between true and false states smoother than ever. Whether you're working with a switch button or a dropdown menu, this hook will make the code clean and easy to manage. You'll wonder how you ever coped in life without it!

import { useState } from "react";

function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);

  const toggle = () => setValue((prev) => !prev);

  return [value, toggle];
}

Usage:

const [isToggled, toggle] = useToggle();

3. useDebounce Hook

Sometimes, it's better to delay. The useDebounce hook is perfect for minimizing the number of calls you make for certain functions, especially in scenarios involving APIs. Whenever a user types in a search box, this hook waits for a pause, so it won't bombard the search with every keystroke!

import { useState, useEffect } from "react";

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}

Usage:

const debouncedSearchTerm = useDebounce(searchTerm, 500);

4. useOnClickOutside Hook

Need an alert when a user clicks outside a menu? With the useOnClickOutside, you can detect clicks outside of an element and manage dropdowns or modals like a breeze. It comes in handy when you want to close these elements by clicking elsewhere on the screen.

import { useEffect } from "react";

function useOnClickOutside(ref, handler) {
  useEffect(() => {
    const listener = (event) => {
      if (!ref.current || ref.current.contains(event.target)) return;
      handler(event);
    };
    document.addEventListener("mousedown", listener);
    document.addEventListener("touchstart", listener);
    return () => {
      document.removeEventListener("mousedown", listener);
      document.removeEventListener("touchstart", listener);
    };
  }, [ref, handler]);
}

Usage:

const modalRef = useRef();
useOnClickOutside(modalRef, () => setIsOpen(false));

5. useInterval Hook

Perfect for handling repeated actions over time, the useInterval hook lets you set up intervals without the mess. Whether it's updating a timer or fetching data regularly, this hook keeps everything tidy and efficient.

import { useEffect, useRef } from "react";

function useInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    if (delay !== null) {
      const id = setInterval(() => savedCallback.current(), delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

Usage:

useInterval(() => {
  setCount((prevCount) => prevCount + 1);
}, 1000);

6. useLocalStorage Hook

The useLocalStorage hook helps you sync state to local storage so that you can cache data easily between user sessions. Perfect for when you need to remember settings or user-specific data across different visits.

import { useState } from "react";

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.log(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.log(error);
    }
  };

  return [storedValue, setValue];
}

Usage:

const [name, setName] = useLocalStorage("name", "Guest");

7. useWindowSize Hook

When you need responsive designs that react to window size changes, useWindowSize is golden. Keep track of window dimensions and handle layout changes with grace.

import { useState, useEffect } from "react";

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return windowSize;
}

Usage:

const { width, height } = useWindowSize();

8. useFetch Hook

Exchanging data over the web? The useFetch hook simplifies those API calls. It's great for data fetching with minimal fuss, helping you build clean and reliable data interactions in your apps.

import { useState, useEffect } from "react";

function 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);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, [url]);

  return { data, loading, error };
}

Usage:

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

Wrapping up, these custom hooks can transform your React development skills and make your coding journey seamless. Every React developer should give these a go to achieve a more efficient workflow.

Happy coding!