React Hooks In DepthLesson 3.1
useEffect hook: side effects and lifecycle in functional components
useEffect syntax, dependency array, cleanup function, component mount/unmount, common side effects, stale closure with deps, effect on every render
useEffect for Side Effects
Side effects are anything that reaches outside React's rendering: API calls, subscriptions, timers, or direct DOM manipulation. useEffect runs after the component renders.
Three Patterns
import { useEffect, useState } from 'react';
function Demo() {
const [count, setCount] = useState(0);
// 1. Runs after EVERY render (no dep array)
useEffect(() => {
document.title = `Count: ${count}`;
});
// 2. Runs ONCE on mount (empty dep array)
useEffect(() => {
console.log('Component mounted');
}, []);
// 3. Runs when 'count' changes
useEffect(() => {
console.log('Count changed to', count);
}, [count]);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}Cleanup Function
Return a cleanup function to cancel subscriptions or timers when the component unmounts or before the effect re-runs:
useEffect(() => {
const timer = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(timer); // cleanup
}, []);All values used inside an effect that come from the component scope must be listed in the dependency array. Missing dependencies cause stale closure bugs where the effect reads outdated values. ESLint's exhaustive-deps rule catches these automatically.
