Effects: sync, then clean up

React chapter 139 · useEffect · dependencies · cleanup · StrictMode · source: react.dev/learn/synchronizing-with-effects

The problem

A chat room connects inside useEffect with no dependency array and no cleanup. Every keystroke re-renders the component, every render runs the effect, and connections pile up — even to rooms you already left.

The pattern that fixes it

Describe one synchronization: useEffect(() => { const c = connect(room); return () => c.disconnect(); }, [room]). React runs it after paint, skips it while room is unchanged, and always cleans up the old room before connecting to the new one.

In plain words

An effect keeps something outside React — a socket, a timer, a subscription — in step with your props and state. The cleanup function is the “undo” React calls before the next run and when the component goes away.

Checking into a hotel room: when you move rooms, you check out of the old one first. The cleanup is the check-out.

Terms

effect
Code React runs after the screen has updated, to sync with something outside React.
dependencies
The values the effect reads. React re-runs it only when one of them changed (Object.is).
cleanup
The function your effect returns. React calls it before re-running the effect and on unmount.

Going deeper

The exact order

Render → commit → (layout effects) → paint → cleanup of the previous effect → the new effect. Cleanup of the old run always happens before the new run, and it sees the old props — which is exactly what you need to disconnect from the old room.

Why StrictMode runs it twice

In development React mounts, unmounts and mounts again. If your effect leaks without cleanup, you see two connections immediately instead of in production a week later. It is a test, not a bug; the fix is a correct cleanup, never removing StrictMode.

You might not need an effect

Deriving data from props (filtering, totals) belongs in render. Reacting to a click belongs in the event handler. Effects are for synchronizing with external systems: network, timers, subscriptions, non-React widgets. Fetching in effects also needs race handling (chapter 98).

Keep learning

More courses

  • Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
  • Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
  • Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
  • System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
  • Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
  • Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
  • Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
  • CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
  • Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
  • Docker — What an image is, why layers cache, and how containers find each other on a network.
  • Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.