JAVASCRIPT
Build a `useDebounce` Custom Hook
Create a custom React `useDebounce` hook to delay execution of a function until after a certain period of inactivity, optimizing performance for frequent events like typing.
import { useState, useEffect } from 'react';
function useDebounce(value, delay) {
// State to store debounced value
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
// Set a timeout to update debounced value after the specified delay
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// Cleanup function to clear the timeout if value or delay changes
// or if the component unmounts. This ensures only the last value is processed.
return () => {
clearTimeout(handler);
};
}, [value, delay]); // Re-run effect if value or delay changes
return debouncedValue;
}
// Example usage component
function DebouncedSearchInput() {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500); // 500ms debounce delay
const [results, setResults] = useState([]);
const [isSearching, setIsSearching] = useState(false);
// Effect to fetch API data when debounced search term changes
useEffect(() => {
if (debouncedSearchTerm) {
setIsSearching(true);
// Simulate an API call
const fetchResults = async () => {
await new Promise(resolve => setTimeout(resolve, 800)); // Simulate network delay
setResults([
`Result for: ${debouncedSearchTerm} 1`,
`Result for: ${debouncedSearchTerm} 2`,
`Result for: ${debouncedSearchTerm} 3`
]);
setIsSearching(false);
};
fetchResults();
} else {
setResults([]);
}
}, [debouncedSearchTerm]); // Only re-run when the debounced term changes
return (
<div>
<h1>Debounced Search</h1>
<p>Type to search. API call will be delayed until you stop typing for 500ms.</p>
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{ width: '300px', padding: '8px', fontSize: '16px' }}
/>
{isSearching && <p>Searching...</p>}
<ul>
{results.map((result, index) => (
<li key={index}>{result}</li>
))}
</ul>
</div>
);
}
export default DebouncedSearchInput;
How it works: The `useDebounce` custom hook takes a `value` and a `delay` as arguments. It returns a new `debouncedValue` that only updates after the `value` has remained unchanged for the specified `delay`. Inside the `useEffect`, a `setTimeout` is set to update `debouncedValue`. Crucially, if the `value` changes again before the timeout completes, the previous timeout is cleared using `clearTimeout`, and a new one is set. This ensures that the `debouncedValue` (and subsequent side effects, like an API call) only triggers once the user has stopped inputting for the debounce duration, preventing excessive function calls and optimizing performance for interactive elements like search bars.