Next.js
Fixing Stale Results in a React Debounced Search
A short React tutorial for preventing earlier search responses from replacing newer ones.
Debounce did not guarantee response order
Typing quickly into a search box sometimes showed results for a query I had already erased. A debounce reduced requests, but a request that had already started could still finish after a newer one.
Cancel both the timer and the request
AbortController gave the effect a clear cleanup path.
useEffect(() => {
const controller = new AbortController();
const timer = setTimeout(async () => {
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
signal: controller.signal,
});
setResults((await res.json()).items);
} catch (error) {
if ((error as Error).name !== "AbortError") setError("Search failed");
}
}, 300);
return () => { clearTimeout(timer); controller.abort(); };
}, [query]);
I also clear results before fetching when the query is empty. Without that branch, old results stay below an empty field.
Test under bad network conditions
Try rapid typing, deletion, and a Slow 3G network profile. Also navigate away while a request is pending. Debounce controls frequency; cancellation controls which response is allowed to update the screen.