Debouncing is a technique used to control how often a function is executed. When an event triggers the function multiple times in quick succession (like typing in a search box or resizing a window), debouncing ensures the function only runs once after a specified period of inactivity has passed since the last trigger.
Common Use Cases:
- Search Input: Wait until the user stops typing before fetching search results.
- Window Resizing: Only recalculate layout after the user finishes resizing the window.
- Button Clicks: Prevent accidental double-clicks from triggering an action multiple times.
- Autocomplete: Delay API calls for suggestions until typing pauses.
This project includes the following custom React hooks for implementing debouncing:
-
useDebounceFunction(fn, waitTime):- Takes a function
fnand awaitTime(in milliseconds, defaults to 400). - Returns a debounced version of the function.
- When the returned function is called, it waits for
waitTimemilliseconds of inactivity before executing the originalfn. - If called again within the
waitTime, the previous timer is cleared, and a new one starts. - The returned function also has a
.cancel()method to manually clear any pending timeout.
- Takes a function
-
useDebounce(value, delay):- Takes a
value(like state fromuseState) and adelay(in milliseconds). - Returns a debounced version of the
value. - The returned value only updates after the input
valuehas stopped changing for the specifieddelay. - Useful for scenarios like delaying actions based on rapidly changing state (e.g., triggering API calls based on user input).
- Uses
useDebounceFunctioninternally.
- Takes a
This is ideal when you want to react to a value (like component state) only after it has stabilized.
// src/components/search.tsx
import { useEffect, useState } from "react";
import { useDebounce } from "../hooks/debounce";
export function SearchComponent() {
const [query, setQuery] = useState('');
// Debounce the query state with a 400ms delay
const debouncedQuery = useDebounce(query, 400);
useEffect(() => {
// This effect runs only when debouncedQuery changes
if (debouncedQuery) {
fetchSearchResults(debouncedQuery);
}
// No need to include 'query' in dependencies, only the debounced value
}, [debouncedQuery]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setQuery(event.target.value);
};
return <input onChange={handleChange} value={query} placeholder="Search..." />;
}
function fetchSearchResults(searchQuery: string) {
console.log("Fetching results for:", searchQuery); // Replace with actual API call
}This is useful when you want to debounce the execution of a specific function or event handler directly.
import { useCallback } from "react";
import { useDebounceFunction } from "../hooks/debounce";
function MyComponent() {
const handleClick = () => {
console.log("Button clicked! Performing action...");
// Perform some action that shouldn't happen too rapidly
};
// Create a debounced version of the handleClick function with a 500ms delay
const debouncedHandleClick = useDebounceFunction(handleClick, 500);
return (
<button onClick={debouncedHandleClick}>
Click Me (Debounced)
</button>
);
}
export default MyComponent;