useEffect & the Dependency Array
useEffect lets a component run side effects — work that reaches outside React, like setting the document title, starting a timer, or subscribing to something — after it renders. The second argument, the dependency array , controls exactly when the effect re-runs, and the function it returns handles cleanup .
Learn useEffect & the Dependency Array in our free React course — a beginner-friendly interactive lesson with runnable examples, a practice exercise and a…
Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
1️⃣ The Dependency Array Controls When It Runs
After each render, React compares every value in the dependency array to its value from the previous render. If any changed, the effect runs again. Three shapes you'll use constantly:
Your turn — write the comparison React uses for a single dependency. It should be true only when the value changed:
2️⃣ Effects Run After the Browser Paints
React renders your component (computing JSX), lets the browser paint, and then runs your effects. That ordering is why effects never block the visible update — and why you read fresh DOM measurements or set the title after render, not during it.
3️⃣ Cleanup — Undo Before You Redo
If your effect starts something that keeps running — a timer, an event listener, a subscription — you must stop it. Return a function from the effect; React runs it before the next effect and when the component unmounts.
These lines form a complete effect that subscribes to a timer and cleans it up. Put them in the right order:
📋 Quick Reference
1. An effect has deps [] . The component re-renders 5 times. How many times does the effect run?
Once. An empty array never changes, so the effect runs only after the first render.
2. You write useEffect(() => setN(n + 1)) with no deps array. What happens?
Infinite loop. It runs after every render, sets state, which re-renders, which runs it again.
3. In what order do render, paint, and the effect happen?
Render → paint → effect. Effects run after the screen is painted.
Model an effect with [count] : it should "set the title" only when count actually changes. Run it and check your output.
Practice quiz
What does the second argument to useEffect (the dependency array) control?
- How fast the effect runs
- Whether the component is memoized
- When the effect re-runs after a render
- The order of multiple effects in a component
Answer: When the effect re-runs after a render. After each render React compares every value in the dependency array to its previous value; if any changed, the effect runs again.
An effect has an empty dependency array []. The component re-renders 5 times. How many times does the effect run?
- Once, after the first render
- 5 times
- 0 times
- 6 times
Answer: Once, after the first render. An empty array never changes, so the effect runs only once after the first render and never again.
What happens if you omit the dependency array entirely?
- The effect never runs
- The effect runs only once
- React throws an error
- The effect runs after every render
Answer: The effect runs after every render. With no dependency array, React runs the effect after EVERY render, which often causes infinite loops if the effect also sets state.
What does returning a function from useEffect do?
- It returns a value to the parent component
- It defines the cleanup that runs before the next effect and on unmount
- It memoizes the effect
- It schedules the effect to run earlier
Answer: It defines the cleanup that runs before the next effect and on unmount. The returned function is the cleanup: React runs it before re-running the effect and when the component unmounts, so you can clear timers, listeners, and subscriptions.
In what order do render, browser paint, and the effect happen?
- Render, then paint, then effect
- Effect, then render, then paint
- Render, then effect, then paint
- Paint, then render, then effect
Answer: Render, then paint, then effect. React renders (computes JSX), the browser paints the screen, and THEN effects run — so effects never block the visible update.
You write useEffect(() => setN(n + 1)) with no dependency array. What happens?
- It runs once and stops
- Nothing, because setN is ignored
- An infinite loop of renders
- It runs only when n changes
Answer: An infinite loop of renders. With no deps it runs after every render; setting state triggers a re-render, which runs the effect again — an infinite loop.
An effect reads a prop but that prop is not in the dependency array. What is the likely bug?
- The effect runs too often
- The effect sees a stale value from an old closure
- React refuses to render
- The cleanup never runs
Answer: The effect sees a stale value from an old closure. If a reactive value the effect reads is missing from deps, the effect keeps the old closure and uses stale data. Add every reactive value it reads.
Why might an effect run twice in development?
- A React bug
- Because the deps array is empty
- Because the component has two effects
- React 18 Strict Mode mounts, unmounts, and remounts to surface missing cleanup
Answer: React 18 Strict Mode mounts, unmounts, and remounts to surface missing cleanup. Strict Mode in development intentionally double-invokes effects to reveal missing cleanup. With correct cleanup it is harmless and does not happen in production.
Which dependency array makes an effect re-run only when count changes?
[count] tells React to re-run the effect whenever the count value differs from its previous render value.
What is a good reason NOT to use an effect?
- When you need to set the document title
- When you subscribe to an external source
- When you can compute the value during render instead
- When you start a timer
Answer: When you can compute the value during render instead. If a value can be computed during render, do that instead of syncing it in an effect — not everything needs useEffect.