React: From Components to Production · State, Events and Effects

Effects: Synchronizing with External Systems

Use useEffect for subscriptions and external sync — and know when you don't need it.

useEffect synchronizes a component with something outside React: subscriptions, timers, DOM APIs, WebSockets, non-React widgets. It runs after render; list every reactive value it uses in the dependency array and return a cleanup function. You don't need an effect to transform data for rendering or to respond to user events — do that during render or in handlers. React 19.2 adds useEffectEvent to read the latest values in effects without re-subscribing.

import { useEffect, useState } from "react";

export function OnlineStatus() {
  const [online, setOnline] = useState(navigator.onLine);

  useEffect(() => {
    const update = () => setOnline(navigator.onLine);
    window.addEventListener("online", update);
    window.addEventListener("offline", update);
    return () => {
      window.removeEventListener("online", update);
      window.removeEventListener("offline", update);
    };
  }, []);

  return <span>{online ? "Online" : "Offline"}</span>;
}

// BUG: Not needed: derived data
// useEffect(() => setFullName(first + " " + last), [first, last]);
// FIX: const fullName = `${first} ${last}`;

Common pitfalls

  • Missing dependencies (stale values) or suppressing the lint rule.
  • Effects that set state derived from props, causing extra renders.
  • No cleanup for subscriptions, intervals or fetches (race conditions).

Key points

  • Effects sync with external systems
  • Always clean up
  • Derive data during render; handle events in handlers

Further reading: react.dev: You might not need an effect

Practice questions

When do you NOT need useEffect?

Answer

For computing values from props/state (do it during render), for responding to user actions (use event handlers), and for resetting state when a prop changes (use a key).

Why must an effect that subscribes to an event return a cleanup?

Answer

Otherwise each re-run or remount adds another listener, causing leaks and duplicate updates; cleanup removes the previous subscription.

Open in the app to mark lessons complete, take notes and track your progress.