Open Hooks

useDebounce

Debounce any changing value in React to improve performance and control effects.

useDebounce

A reusable React hook to debounce any value. It delays updating the returned value until after the specified delay period has passed without changes. Useful for optimizing performance in high-frequency state updates like search input or resize events.


📦 Installation

This hook is framework-independent and works in React and Next.js projects.

No external dependency needed

🧠 Purpose

useDebounce helps prevent frequent re-renders or side-effects by only acting on the final value after a specified period of inactivity.


💡 Use Cases

  • Delay search queries while typing
  • Reduce API calls on input changes
  • Debounce expensive calculations
  • Handle scroll/resize events efficiently

📁 Hook Code

useDebounce.ts
import { useState, useEffect } from "react";

export function useDebounce<T>(value: T, delay: number = 500): T {
    const [debounced, setDebounced] = useState(value);

    useEffect(() => {
        const timer = setTimeout(() => setDebounced(value), delay);
        return () => clearTimeout(timer);
    }, [value, delay]);

    return debounced;
}
useDebounce.js
import { useState, useEffect } from "react";

export function useDebounce(value, delay = 500) {
    const [debounced, setDebounced] = useState(value);

    useEffect(() => {
        const timer = setTimeout(() => setDebounced(value), delay);
        return () => clearTimeout(timer);
    }, [value, delay]);

    return debounced;
}

🧪 Example

import { useState, useEffect } from "react";
import { useDebounce } from "@/hooks/useDebounce";

export default function SearchBar() {
    const [query, setQuery] = useState("");
    const debouncedQuery = useDebounce(query, 500);

    useEffect(() => {
        if (debouncedQuery) {
            console.log("Triggering API call with:", debouncedQuery);
            // callSearchAPI(debouncedQuery);
        }
    }, [debouncedQuery]);

    return (
        <input
            type="text"
            placeholder="Search here..."
            value={query}
            onChange={(e) => setQuery(e.target.value)}
        />
    );
}
import { useState, useEffect } from "react";
import { useDebounce } from "@/hooks/useDebounce";

function SearchBar() {
    const [query, setQuery] = useState("");
    const debouncedQuery = useDebounce(query, 500);

    useEffect(() => {
        if (debouncedQuery) {
            console.log("Triggering API call with:", debouncedQuery);
            // callSearchAPI(debouncedQuery);
        }
    }, [debouncedQuery]);

    return (
        <input
            type="text"
            placeholder="Search here..."
            value={query}
            onChange={(e) => setQuery(e.target.value)}
        />
    );
}

🧩 Hook Signature

function useDebounce<T>(value: T, delay: number): T;

📝 Parameters

PropTypeDefault
delay?
number
500
value
T
-

🎯 Returns

PropTypeDefault
debouncedValue
T
-

🧪 Testing Tip

Log both query and debouncedQuery to clearly see the difference during typing:

console.log({ query, debouncedQuery });

🧯 Visual Timeline

Debounce Flow Explanation

When the user types quickly, the debounce timer resets. Only after the user stops typing for the specified delay does the debounced value update.

  User types: h he hel hell hello Time passed: -- 100 200 300 400ms {" "}
  debounce timer resets
  Debounced value: hello (after 500ms pause)

🏁 Summary

  • ✅ Clean, reusable hook
  • ✅ Works in both JS and TS
  • ✅ Ideal for search, resize, or scroll performance
  • ✅ Simple to use and extend

🙋 Contribution

Found a bug or improvement? Submit a PR on GitHub