How would you write a useDebounce hook for a search box?
Keep a debounced copy of the value in state. In an effect, start a setTimeout that updates the copy after a delay, and clear that timer in the cleanup so only the last change within the delay goes through.
Explain it simply
When you type "react hooks" in a search box, firing a request on every letter wastes bandwidth. Debouncing waits until you pause typing for, say, 400 ms, and only then uses the latest text.
The trick is the cleanup function. Each keystroke re-runs the effect: the previous timer is cleared, and a new one starts. Only a value that survives the full delay without being replaced reaches the state.
The component then fetches using the debounced value, not the raw input.
Choose the delay by feel: 300 to 500 ms suits search boxes, while a form validation check may use less. A longer delay saves more requests but makes the page feel slow to respond.
Example
function useDebounce(value, delay = 400) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
return debounced;
}
function Search() {
const [q, setQ] = useState("");
const term = useDebounce(q);
useEffect(() => { if (term) fetch(`/api/search?q=${term}`); }, [term]);
return <input value={q} onChange={e => setQ(e.target.value)} />;
}What to say in the interview
"I store a debounced value in state and update it from a timeout inside an effect. The cleanup clears the previous timeout on every change, so only the last value after the pause is applied. The component uses the debounced value for requests while the input stays instantly responsive."
Common mistakes
- Forgetting clearTimeout, so every keystroke still fires its own update.