Understanding useEffect in React with Practical Examples
A clear, example-driven guide to the useEffect hook — dependencies, cleanup, data fetching, and the most common mistakes to avoid.
useEffect lets a component run side effects after it renders — things like
fetching data, setting up subscriptions, or starting a timer. The hardest part
isn't the syntax, it's understanding when the effect runs.
The dependency array
The second argument decides how often the effect runs:
// Runs after every render
useEffect(() => {
console.log("rendered");
});
// Runs once, after the first render
useEffect(() => {
console.log("mounted");
}, []);
// Runs whenever `userId` changes
useEffect(() => {
loadUser(userId);
}, [userId]);Leaving a value out of the dependency array doesn't make the bug go away — it just hides it. The effect will read a stale value from an earlier render.
Cleanup functions
If your effect starts something, it should also stop it. Return a function and React runs it before the next effect and when the component unmounts:
useEffect(() => {
const id = setInterval(() => tick(), 1000);
return () => clearInterval(id); // cleanup
}, []);Fetching data safely
Use an AbortController so a request that's still in flight doesn't update state
after the component has gone away:
useEffect(() => {
const controller = new AbortController();
fetch("/api/users", { signal: controller.signal })
.then((res) => res.json())
.then(setUsers)
.catch((err) => {
if (err.name !== "AbortError") setError(err);
});
return () => controller.abort();
}, []);Here's that exact pattern, live — open the network tab and hit Refresh:
Users
Common mistakes
- Missing dependencies — the effect captures stale props or state.
- Objects/arrays in deps — they're recreated each render, so the effect runs
every time. Memoize them with
useMemo/useCallback. - Setting state synchronously in the effect body, causing extra renders. Set state in response to an event or after an awaited result instead.
Master the dependency array and cleanup, and useEffect stops being mysterious.