Course outline · 0% complete

0/28 lessons0%

Course overview →

Side effects and the dependency array

lesson 7-1 · ~12 min · 19/28

Quiz

Warm-up from lessons 1-2 and 3-3: rendering in React should be a pure computation, same data in, same UI out. Which of these does NOT belong inside the render itself?

Side effects and useEffect

A side effect is anything a component does beyond computing its JSX: fetching data, starting a timer, subscribing to a websocket, updating document.title. Effects cannot run during render, render must stay pure. React's home for them is the useEffect hook:

import { useEffect } from "react";

function Profile({ userId }) {
  useEffect(() => {
    document.title = "Profile of user " + userId;
  }, [userId]);

  return <h1>User {userId}</h1>;
}

useEffect(setup, deps) takes a function and a dependency array. React renders first, commits the DOM, and then runs your effect. The deps control how often.

The dependency array, three modes

useEffect(() => { ... });          // no array: after EVERY render
useEffect(() => { ... }, []);      // empty array: after the FIRST render only
useEffect(() => { ... }, [a, b]);  // after renders where a or b changed

Two words you will meet constantly around effects: a component mounts when React adds it to the screen for the first time, and unmounts when React removes it, say, the user navigates to a different page. So "after the FIRST render only" means: once, at mount.

React compares each dependency to its value from the previous render with Object.is, the same identity comparison from lesson 4-3. All the same rules apply: a mutated object looks unchanged, a fresh object always looks changed.

The golden rule: every value from the component that the effect reads belongs in the array. Props, state, anything computed from them. Leaving one out means the effect keeps using a stale snapshot of it, one of the hardest bugs to spot in React. Editors with the React lint rules will tell you exactly what is missing, take the suggestion.

render 1effect runsrender 2deps same:effect skippedrender 3deps changed:cleanup + effectrender 4deps same:effect skippedunmountfinal cleanuplife of one useEffect(..., [dep])
The life of an effect with a dependency array. It runs after the first render, re-runs (after cleanup) only when a dependency changed, and cleans up at unmount. The gold marker walks the timeline.

Quiz

Predict the behavior: ```jsx function Clock() { const [time, setTime] = useState(""); useEffect(() => { setTime(new Date().toLocaleTimeString()); }, []); return <p>{time}</p>; } ``` How often does the effect run?

Quiz

Spot the bug: ```jsx function Results({ query }) { const [data, setData] = useState(null); useEffect(() => { loadResults(query).then(setData); }, []); return <List data={data} />; } ```