In React function components, we often need to run side effects, like:
- Fetching data
- adding / removing event listener (scroll, resize)
- Manipulating the componentDidMount
- Starting or clearing timers
In class components, this logic was handled in componentDidMount, componentDidUpdate, and componentWillUnmount. In function components, the tool for this is uesEffect.
Definition
useEffect is hook that let you run side effects after rendering and after DOM is updated It can also return a cleanup function to remove resources when needed.
Syntax:
useEffect(() => {
// side effect
return () => {
// cleanup (optional)
};
}, [dependencies]);
When does useEffect run with setState?
Here’s what happens when you call setState:
- setState is called → React schedules a re-render
- Render phase → React runs the component to produce Virtual DOM
- Commit phase → React updates the real DOM
- useLayoutEffect runs synchronously (before paint)
- Browser paints → user sees the updated UI
- useEffect runs asynchronously (after paint)
👉 This means: the screen updates first, then useEffect runs.
Dependency Array
- No array → runs after every render
- Empty array
[]→ runs only once, after the first render - Specific dependencies
[value]→ runs whenever those values change
cleanup
You can return a cleanup function:
- Runs before the next effect, or when the componet unmounts
- Prevents memory leaks
useEffect(() => {
const handler = () => console.log("resized");
window.addEventListener("resize", handler);
return () => {
window.removeEventListener("resize", handler);
};
}, []);
Common Mistakes
- Doing API calls directly in render → should be in
useEffect - Forgetting cleanup → memory leaks
- Wrong dependency array → stale data or infinit re-renders
- Unconditional
setStateinside effect → infinie loop
Summary
useEffect= side effect manager for function components- Runs after render and after the UI is painted
- Three dependency modes: every render, once, or on specific changes
- Cleanup prevents leaks and handles unmounting
- Difference from
useLayoutEffect: async vs sync timing