Why this matters

The bug. Each query change spawns a new fetch, but old fetches don't get cancelled. Network ordering is non-deterministic — the slow earlier request can land *after* the fast later one and clobber the correct results.

The fix. Use the effect cleanup to ignore stale responses (or, modern: pass an AbortSignal and abort on cleanup):

useEffect(() => { let cancelled = false; fetch(...).then(data => { if (!cancelled) setResults(data) }); return () => { cancelled = true }; }, [query]);

Pattern. Any time you setState from an async result inside an effect, ask: what if this is stale?

Review heuristic

Every check-then-act over shared state is a race waiting for production load. Look for read-then-write pairs that aren't inside a transaction, a lock, or an atomic CAS. If you can articulate the bug as "if two requests arrive at the same time, both will...", it's a race.

External reference: CWE-362: Concurrent Execution using Shared Resource.