Quantum Tech Newz Logo
HomeAboutWhat’s NewAIReactJS

Creative Use Cases for Custom Hooks in React (With Examples)

Last updated - 08 June, 2025, 10 minute reading

React has revolutionized how developers build user interfaces. One of its standout features is Hooks, introduced in React 16.8. While built-in hooks like useState and useEffect are staples in most applications, custom hooks allow developers to abstract and reuse logic across components with elegance and clarity.

In this blog, we'll explore unique and practical use cases for custom hooks, complete with real-world examples that go beyond the common “form validation” or “fetch data” use cases.

What is a Custom Hook?

A custom hook is a special JavaScript function that starts with the word "use" and can include other hooks. It helps you organize and reuse shared logic across different components in your app.


// Basic structure
function useMyHook() {
  const [state, setState] = useState(null);
  // logic here...
  return state;
}

1. usePrevious : Track Previous Value of a Prop or State

Sometimes you need to know what the previous value of a state or prop was — for example, to detect if a value has changed meaningfully.

Code Example:


import { useRef, useEffect } from 'react';

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

Usage:


const MyComponent = ({ count }) => {
  const prevCount = usePrevious(count);

  useEffect(() => {
    if (prevCount !== undefined && count > prevCount) {
      console.log('Count increased!');
    }
  }, [count]);

  return <div>Count: {count}</div>;
};

2. useInterval : Set Up Declarative Intervals

Timers can be tricky in React, especially when working with state. This custom hook makes it easier to handle intervals declaratively.


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:


const Timer = () => {
  const [seconds, setSeconds] = useState(0);

  useInterval(() => {
    setSeconds(prev => prev + 1);
  }, 1000);

  return <div>{seconds} seconds elapsed.</div>;
};

3. useDarkMode: Sync Theme with LocalStorage & System Preferences

Want to provide a dark mode toggle that persists and respects system settings? Here's a clever hook.

Code Example:


function useDarkMode() {
  const [enabled, setEnabled] = useState(() => {
    const saved = localStorage.getItem('dark-mode');
    return saved !== null ? JSON.parse(saved) : window.matchMedia('(prefers-color-scheme: dark)').matches;
  });

  useEffect(() => {
    localStorage.setItem('dark-mode', JSON.stringify(enabled));
    document.body.classList.toggle('dark-mode', enabled);
  }, [enabled]);

  return [enabled, setEnabled];
}

Usage:

const DarkModeToggle = () => {
  const [darkMode, setDarkMode] = useDarkMode();

  return (
    <button onClick={() => setDarkMode(prev => !prev)}>
      {darkMode ? 'Disable' : 'Enable'} Dark Mode
    </button>
  );
};

4. useUndoRedo: Implement Undo/Redo for Complex State

This hook is useful for drawing apps, text editors, or any scenario where the user might want to undo or redo changes.

Code Example:

function useUndoRedo(initialValue) {
  const [past, setPast] = useState([]);
  const [present, setPresent] = useState(initialValue);
  const [future, setFuture] = useState([]);

  const set = (newPresent) => {
    setPast([...past, present]);
    setPresent(newPresent);
    setFuture([]);
  };

  const undo = () => {
    if (past.length === 0) return;
    const previous = past[past.length - 1];
    const newPast = past.slice(0, -1);
    setPast(newPast);
    setFuture([present, ...future]);
    setPresent(previous);
  };

  const redo = () => {
    if (future.length === 0) return;
    const next = future[0];
    const newFuture = future.slice(1);
    setPast([...past, present]);
    setPresent(next);
    setFuture(newFuture);
  };

  return { present, set, undo, redo, canUndo: past.length > 0, canRedo: future.length > 0 };
}

Usage:

const UndoableInput = () => {
  const { present, set, undo, redo, canUndo, canRedo } = useUndoRedo("");

  return (
    <div>
      <input value={present} onChange={e => set(e.target.value)} />
      <button onClick={undo} disabled={!canUndo}>Undo</button>
      <button onClick={redo} disabled={!canRedo}>Redo</button>
    </div>
  );
};

5. useNetworkStatus: Detect Online/Offline Status

This custom hook can help you inform users about their connectivity status or trigger background syncs.

Code Example:


import { useState, useEffect } from 'react';

function useNetworkStatus() {
  const [online, setOnline] = useState(navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setOnline(true);
    const handleOffline = () => setOnline(false);

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return online;
}

Usage:


const StatusBanner = () => {
  const isOnline = useNetworkStatus();

  return <div>{isOnline ? '🟢 You are online' : '🔴 You are offline'}</div>;
};

FAQs

What is a custom hook in React?
A custom hook is a function that starts with use and contains reusable hook logic. It helps avoid code duplication in React apps.

How do I create a custom hook?
Use a regular function prefixed with use, and write your logic using built-in React hooks like useState or useEffect.

Why should I use custom hooks?
They improve code reuse, readability, and maintainability, especially in complex components.

Can you give a simple example of a custom hook?
Yes! A useWindowWidth hook returns the current window width using useState and useEffect.

Final Thoughts

Custom hooks are more than just tools for abstraction — they’re a way to rethink how you build your components. From handling timers and theme preferences to enabling undo/redo functionality, custom hooks make your components cleaner, smarter, and more maintainable.

Next time you're repeating logic across multiple components or want to encapsulate a specific behavior, consider writing a custom hook. You might just end up creating something you’ll reuse in every project.


Sudhir Yadav, Senior Software Engineer


© 2025 Quantum Tech Newz — All rights reserved.

Privacy Policy