useEffect(() => {
let ignore = false;
fetchResults(query).then(json => {
if (!ignore) setResults(json);
});
return () => { ignore = true; };
}, [query]);
Responses can arrive out of order, so an old response can overwrite newer results. Prevent it with an effect cleanup that ignores or cancels the old request.
For example, the user types a, then ab. Now two requests are in flight. If the request for a is slower, its response lands last. It then overwrites the correct results for ab.
The fix is cleanup:
- Keep an
ignoreflag in the effect, starting asfalse. - Set it to
truein the cleanup. - Only call
setStateif it is stillfalse.
When the dependency changes, React runs the old cleanup first. So stale responses are dropped. You can also pass an AbortController signal to fetch and call abort() in the cleanup. This cancels the request itself.
In practice, frameworks or libraries like TanStack Query handle caching, deduplication and races for you. So keep raw effect fetching simple.
- Responses can arrive out of order and overwrite newer data.
- Use an
ignoreflag that the cleanup function sets totrue. - Or abort the request with
AbortControllerin the cleanup. - Cleanup runs before the next effect, so stale results are thrown away.
- Data libraries and frameworks handle caching and races for you.