Debugging race conditions in async React state
The symptom was always the same: a component updated with data from a request the user had already navigated away from. No error, no warning — just a state update that landed a beat too late.
The fix isn’t a library. It’s tracking whether the component is still mounted before the update lands, and cancelling the update if it isn’t.
function useAsyncState(initial) {
const [state, setState] = useState(initial);
const mounted = useRef(true);
useEffect(() => {
return () => { mounted.current = false; };
}, []);
const safeSet = (value) => {
if (mounted.current) setState(value);
};
return [state, safeSet];
}