Mount, Update, Unmount — Effect Cleanup
A reading timer counts the minutes you spend on a book. Open it, close it, open it again — and if nothing stops the first timer, you now have two ticking. Every effect that starts something needs a way to stop it, and React tells you exactly when.
The rule
Every setup gets a cleanup: before the next run, and at unmount.
A component has a simple life:
- Mount — it appears on the page for the first time.
- Update — it re-renders with new props or state, possibly many times.
- Unmount — it is removed from the page.
An effect can return a function. That function is the cleanup:
function ReadingTimer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const id = setInterval(() => setSeconds(s => s + 1), 1000); // setup
return () => clearInterval(id); // cleanup
}, []);
return <p>Reading for {seconds}s</p>;
}React calls the cleanup at two moments:
- Before the effect runs again, if its dependencies changed — so the old setup is undone before the new one starts.
- When the component unmounts — so nothing is left running.
Setup and cleanup come in pairs: setInterval / clearInterval, addEventListener / removeEventListener, connect / disconnect.
Notice setSeconds(s => s + 1): the updater form lets the effect keep [] as its dependencies. Writing setSeconds(seconds + 1) would lock in the seconds from the first render, and the display would stick at 1.
Strict Mode's extra check. In development React mounts each component, immediately runs its cleanup, then sets it up again. If your effect lacks a cleanup, you see the bug straight away — for example, the timer counting twice as fast. In production it runs once.
The shortcut
Say the setup line aloud, then say its opposite. If you cannot name the opposite, check whether you really needed an effect.
Mount with bookId "b1"
Setup runs: subscribe to updates for
b1.
Drills
Answer fast — trust the rule.
How does an effect declare its cleanup?
An effect depends on [bookId]. bookId changes from b1 to b2. What runs, in order?
What is the right cleanup for window.addEventListener('resize', onResize)?
In development only, a timer effect without cleanup counts twice as fast. Why?
Remember
- Every setup gets a cleanup: before the next run, and at unmount.
- Say the setup, then say its opposite — that is your cleanup.
- Trap: timers and listeners that outlive the component.
