React useEffect Hook – A Beginner’s Guide
25 April 2025 | Category: React Js
React is not just about displaying things—sometimes, we want our app to “do something” after rendering. This is where the useEffect
hook comes in.
Think of useEffect
as a way to run side effects in your React components.
📦 What is a Side Effect?
In React, a side effect is any action that happens outside of the component or affects something outside of it.
Examples of side effects:
- Fetching data from an API
- Setting up a timer
- Updating the document title
- Subscribing to a service
🧠 What is useEffect
?
useEffect
is a React Hook that allows you to run side effects in functional components.
📘 Syntax:
useEffect(() => {
// side effect code
}, [dependencies]);
- The first argument is a function that runs after the component renders.
- The second argument is an array of dependencies. It tells React when to run the effect.
✅ Basic Example – Change Document Title
import React, { useState, useEffect } from 'react';
function TitleUpdater() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Clicked ${count} times`;
});
return (
<div>
<h1>You clicked {count} times</h1>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</div>
);
}
export default TitleUpdater;
🧠 What’s Happening?
- Each time the component renders (when
count
changes),useEffect
runs. - It updates the browser tab title with the current click count.
🛠️ Controlling When useEffect
Runs
The dependency array [ ]
controls how often useEffect
runs:
🔁 1. Run on Every Render (No Dependency Array)
useEffect(() => {
console.log("Runs after every render");
});
🔂 2. Run Only Once (Empty Dependency Array)
useEffect(() => {
console.log("Runs only once after first render");
}, []);
This is perfect for API calls or initial setup.
🔄 3. Run When Specific Values Change
useEffect(() => {
console.log("Runs when count changes");
}, [count]);
Only re-runs the effect if count
changes.
🔄 Cleanup with useEffect
Some side effects (like event listeners or timers) need cleanup to avoid memory leaks.
🧹 Example: Timer Cleanup
useEffect(() => {
const timer = setInterval(() => {
console.log('Tick');
}, 1000);
return () => {
clearInterval(timer); // clean up the timer
console.log('Timer cleared');
};
}, []);
- The function returned inside
useEffect
runs during cleanup (when component unmounts or before running the effect again).
🌐 Example: Fetch Data from API
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(data => setUsers(data));
}, []);
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
✅ This effect runs only once, because the dependency array is empty ([]
).
⚠️ Common Mistakes
❌ Forgetting the dependency array:
// This runs after every render (not good for fetch!)
useEffect(() => {
fetchData();
});
✅ Fix:
useEffect(() => {
fetchData();
}, []); // only once
❌ Updating state inside useEffect without checking dependencies:
useEffect(() => {
setCount(count + 1); // causes infinite loop!
});
✅ Fix: Use correct dependencies or avoid unnecessary updates.
✅ Summary Table
Use Case | Dependency Array | Runs When… |
---|---|---|
Run on every render | ❌ Not included | After every render |
Run only once (on mount) | [] | After first render only |
Run when value changes | [value] | When value changes |
Cleanup side effect | return () => {} | On unmount or before re-run |
💡 Final Thoughts
The useEffect
hook is powerful—it lets your component react to changes in a controlled way. As you build more real-world apps, you’ll use it for:
- Data fetching
- Animations
- DOM updates
- Subscriptions
- Timers
Mastering
useEffect
is essential to mastering React.