You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
During rendering, React components should be pure — they should only compute and return JSX without causing observable changes outside the function. However, real applications need to do things like fetching data, subscribing to events, setting timers, and manually updating the DOM. These are called side effects.
The useEffect Hook lets you run side effects after React has rendered the component.
import { useEffect, useState } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => clearInterval(id); // cleanup
}, []); // empty deps array = run once on mount
return <p>Elapsed: {seconds}s</p>;
}
useEffect takes two arguments: an effect function and an optional dependency array.
The dependency array controls when the effect re-runs:
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]); // re-runs whenever count changes
Always include every reactive value used inside the effect in the dependency array. Omitting dependencies is a common source of bugs.
When an effect sets up a subscription, timer, or event listener, it should clean up after itself to avoid memory leaks. Return a cleanup function from the effect:
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
React calls the cleanup function before running the effect again and when the component unmounts.
A very common pattern is fetching data on mount:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then((res) => res.json())
.then((data) => {
if (!cancelled) setUser(data);
});
return () => { cancelled = true; };
}, [userId]); // re-fetch whenever userId changes
if (!user) return <p>Loading...</p>;
return <p>{user.name}</p>;
}
The cancelled flag prevents setting state on an unmounted component if the user navigates away before the fetch completes.
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.