React Best Practices

Chapter 3 · Practice 2 of 4

Return a cleanup from every effect that subscribes or starts work

From Effects, and when you do not need one

Why it matters

If an effect connects, subscribes, adds a listener or starts a timer, it must undo that in its cleanup function. Without cleanup you:

  • leak listeners,
  • keep sockets open after the component is gone,
  • see duplicated events.

In development, Strict Mode mounts, unmounts and mounts every component again to check that your cleanup works. If something breaks or doubles in that check, the cleanup is missing or incomplete.

In React 19.3, Strict Mode also double-invokes effects during hydration, so server-rendered pages get the same check.

Example

TSX
useEffect(() => {
  const controller = new AbortController();
  window.addEventListener('resize', onResize, { signal: controller.signal });
  return () => controller.abort();
}, []);