Effects that subscribe to external systems must clean up to avoid memory leaks and duplicate listeners. Return a function from useEffect; React calls it before re-running the effect and on unmount.
Common cleanup targets
clearInterval/clearTimeout- WebSocket or event listener removal
- AbortController for in-flight fetches
- Resetting document title or body scroll lock
Strict Mode double invoke
In development, React 18 Strict Mode may mount, unmount, and remount to surface missing cleanups. Your cleanup function should make remounting safe.
Self-check
- When does React call your cleanup function?
- Why leave a timer running after unmount?