An Effect synchronises a component with something outside React: a network connection, timer, browser API or third-party widget. If a value can be calculated during rendering or changed in an event handler, you probably do not need an Effect.
When to use an Effect
import { useEffect } from "react"; useEffect(() => { document.title = `${remaining} tasks remaining`; }, [remaining]);
Setup and cleanup
If setup creates a subscription, connection or timer, return a cleanup function that reverses it. React runs cleanup before re-running the Effect with changed dependencies and after the component is removed.
useEffect(() => { const id = window.setInterval(refresh, 30000); return () => window.clearInterval(id); }, [refresh]);
Dependencies
Include every reactive value read by the Effect. Do not hide dependencies to control when it runs; restructure the code instead. Development mode may run setup and cleanup an extra time to reveal missing cleanup, so write each Effect as an independent synchronisation process.
The Effect timeline
React first renders and commits the screen. It then runs the Effect setup. When a dependency changes, React renders with the new value, runs the previous cleanup and then runs setup again. On removal it runs the final cleanup. Thinking in setup/cleanup pairs is more accurate than thinking only in terms of mounting.
An empty dependency array means the Effect does not depend on changing component values. It is not a way to silence the dependency checker. If setup reads a prop or state value, that value normally belongs in the array.
Challenge: synchronise online status
Build a component that displays whether the browser is online. Initialise state from navigator.onLine, subscribe to the window's online and offline events in an Effect, and remove both listeners in cleanup.
Use the browser developer tools to simulate offline mode. Confirm that navigating away and back does not create duplicate listeners.
