Race conditions React : les 4 patterns qui les éliminent
Une race condition = 2 opérations async dont l'ordre n'est pas garanti. En React, c'est le bug "1 fois sur 50" impossible à reproduire en dev.
Les 4 cas les plus fréquents
| Cas | Symptôme | Solution |
|---|---|---|
| Double fetch sur même resource | 2 setStates, ordre indéterminé | React Query (dedup native) |
| Fetch après unmount | Warning "setState on unmounted" | AbortController dans useEffect |
| Click pendant requête en cours | Soumission double, doublon en DB | Disable button + flag isPending |
| Navigation pendant fetch | Données affichées sur mauvaise page | AbortController + cleanup |
Pattern 1 : AbortController
useEffect(() => {
const ctrl = new AbortController();
fetch(url, { signal: ctrl.signal })
.then(setData)
.catch(e => { if (e.name !== "AbortError") throw e });
return () => ctrl.abort();
}, [url]);Pattern 2 : flag isPending (mutations)
Toute mutation expose isPending. Button disabled tant que true. Sinon : 1 user excité → 3 requêtes → 3 lignes en DB.
Pattern 3 : React Query / SWR
Dedup, cache, refetch sur focus, gestion stale gratuite. Ne pas réinventer.
Pattern 4 : optimistic update + rollback
UI update immédiat, rollback si l'API échoue. Évite le "j'attends 800ms et je crois que ça a marché". useMutation({ onMutate, onError }).
Anti-pattern : setState dans .then() sans guard
fetch().then(data => setState(data)) après unmount = warning + memory leak. Toujours AbortController OU vérifier isMounted via ref.
Partager