Hooks

useEffect, races & when not to use it

Dependencies, cleanup, race conditions, and effect-vs-render distinctions.

advanced Experienced

useEffect synchronises a component with external systems — network, subscriptions, timers, non-React widgets — running after paint. The dependency array declares what it reads; a correct array is essential.

An effect is a subscription to the outside world with an unsubscribe note attached; forget the note and old broadcasts keep overwriting your screen.

Key concepts

1
Race conditions: if an effect fetches on id and id changes fast, an older response can overwrite a newer one. Guard with an ignore flag or an AbortController in cleanup.
Race conditions:idignoreAbortController
2
Modern React guidance: you might not need an effect. Derived data belongs in render/useMemo; responding to events belongs in handlers. Effects are for genuine external synchronisation, not for chaining state.
you might not need an effectuseMemo
3
Pitfall: empty deps [] with a stale closure reading old state. useLayoutEffect runs synchronously before paint (measure/mutate DOM) — use sparingly. Interview angle: "how do you prevent a stale fetch from clobbering fresh state?" — cleanup flag / abort.
Pitfall:Interview angle:[]useLayoutEffect