useEffect Hook¶
The useEffect
hook lets you perform side effects in functional components — like fetching data, setting up subscriptions, timers, or manually changing the DOM.
1. Basic Syntax¶
useEffect(() => {
// code to run after render
}, [dependencies]);
- Runs after every render by default
- The second argument (dependency array) controls when it runs
2. No Dependency Array¶
useEffect(() => {
console.log("Runs after every render");
});
- Executes after every re-render
3. Empty Dependency Array []
¶
useEffect(() => {
console.log("Runs once on mount");
}, []);
- Runs only once when the component is mounted (like
componentDidMount
)
4. With Dependencies¶
useEffect(() => {
console.log("Runs when count changes");
}, [count]);
- Runs when
count
changes - Add all external state/props used in the effect to the array
5. Cleanup Function¶
Return a function inside useEffect
to handle cleanup (e.g., remove event listeners, clear intervals):
useEffect(() => {
const id = setInterval(() => {
console.log("tick");
}, 1000);
return () => {
clearInterval(id); // cleanup on unmount or re-run
};
}, []);
6. Fetching Data Example¶
import { useState, useEffect } from "react";
function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://api.example.com/users")
.then(res => res.json())
.then(data => setUsers(data));
}, []);
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
7. Multiple Effects¶
You can use useEffect
multiple times per component for separation of concerns.
useEffect(() => {
// first effect
}, [a]);
useEffect(() => {
// second effect
}, [b]);
8. Infinite Loop Warning¶
Don’t update state directly inside useEffect
without a condition or it will cause an infinite render loop.
useEffect(() => {
setCount(count + 1); // BAD: triggers render → runs again
});