Rapid changes in searches or navigation generate multiple simultaneous requests. Without control, the response that arrives last (even if it contains obsolete data) will overwrite the state, displaying incorrect information. A silent but critical error.
The Problem: Race Conditions
When the order of responses does not match the order of requests.

Common Code (The Error)
- Click A → "Data A" is requested
- Click B → "Data B" is requested
- Network: B arrives (Fast) → UI shows "Data B" ✓
- Network: A arrives (Late) → UI overwrites with "Data A" ✗
Even though the user clicked B last and wants to see those data, the interface ends up showing obsolete information from A. This happens because each request updates the state without verifying if it is still relevant.
The Solution (AbortController)
The key to solving this is canceling the previous request before firing the new one. The native AbortController API allows us to do this elegantly:
useEffect(() => {
const controller = new AbortController(); // 1. We create the controller
fetch(`/api/user/${id}`, { signal: controller.signal }) // 2. We pass the signal
.then(data => setUser(data))
.catch(err => {
if (err.name !== 'AbortError') {
// We handle only real errors, not cancellations
}
});
// 3. Cleanup function: we cancel if the component
// unmounts or the ID changes
return () => controller.abort();
}, [id]);
Top comments (0)