useEffect Hook
useEffect runs after the browser paints. That is where fetch, subscriptions, document.title, and timers belong — not in the middle of render. If you fetch during render, you can start a request on every paint and freeze the tab. Effect means: after this UI is on screen, do this extra work.
The dependency array lists values the effect reads. [] → run after first paint, cleanup on unmount (≈ componentDidMount + willUnmount). [userId] → run again when userId changes. Omit the array entirely → run after every paint. If that effect calls setState, you can get an infinite loop. That is the exam trap.
Return a cleanup function. Timers: clearInterval. Listeners: removeEventListener. Fetch: abort or a dead flag so a late response does not setState on an unmounted screen. Forget cleanup, leave the page, ghost timers keep firing. Strict Mode in development may run mount → cleanup → mount on purpose to catch this. Don’t ‘fix’ it by removing Strict Mode. Fix the effect.
Let’s do a clock on the board. useState(0) for seconds. useEffect(() => { const id = setInterval(() => setT(x => x + 1), 1000); return () => clearInterval(id); }, []); Screen: 0s, 1s, 2s. Leave the page → interval dies. That story is lifecycle in hooks language.
Fetching: useEffect(() => { let dead = false; fetch('/api/user/' + id).then(r => r.json()).then(d => { if (!dead) setUser(d); }); return () => { dead = true; }; }, [id]); When id changes, cleanup ignores the old request, new request starts. Without that, user A’s slow response can overwrite user B.
Trap: missing deps (eslint exhaustive-deps is your friend). Trap: putting objects/arrays inline in deps so the effect runs every render. Trap: using useEffect to copy props into state for no reason — usually you should just render the prop. Trap: thinking useEffect runs before paint (that is closer to useLayoutEffect, a rarer tool).
useEffect Hook — mount fetches count. Leave page → dead flag ignores late JSON. [] means once.
render
│ paint
▼
useEffect
│ unmount / deps change
▼
cleanup()After paint + deps + cleanup. Mention Strict Mode double invoke.