If you’re new to React, one thing that often confuses beginners is when and why to use useEffect. Let’s break it down slowly, so it makes perfect sense even if you’ve never done frontend before.
1. What is useEffect?
useEffect is a React Hook that lets you perform side effects in a component.
Side effects are things your component does that are outside rendering the UI:
- Fetching data from an API
- Logging to the console
- Setting timers (
setTimeout) - Interacting with browser APIs (like
localStorage)
In plain terms:
“useEffect is a way to tell React: do this action after the component appears on the page or when something changes.”
2. When do you actually need it?
Think of useEffect as React’s way of replacing old lifecycle methods from class components:
| Old React class method |
useEffect equivalent |
Typical use |
|---|---|---|
componentDidMount |
useEffect(() => { ... }, []) |
Run once on page load |
componentDidUpdate |
useEffect(() => { ... }, [dependency]) |
Run when a value changes |
componentWillUnmount |
useEffect(() => { return () => {...} }, []) |
Clean up before component disappears |
2.1 Backend Analogy
If React were a backend server:
-
useEffect(() => fetchData(), [])→ “Call the database once when the request starts” -
useEffect(() => fetchData(), [userId])→ “Call the database every time the userId changes”
This makes it very intuitive if you already understand API calls and triggers.
3. The Basic Syntax
useEffect(() => {
// code you want to run
}, [dependencies]);
Breaking it down:
- First argument: A function containing the code you want to run (your “effect”)
- Second argument: An array of dependencies that tells React when to run the effect
3.1 Dependency Array []
- Empty array
[]→ Run once, after the component loads - Example:
useEffect(() => {
console.log("Component loaded!");
}, []);
Think of it like onPageLoad.
3.2 Dependencies [value]
- Add values inside the array → Run every time one of these values changes
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`Count changed to: ${count}`);
}, [count]);
Here, the effect only runs when count changes.
Backend analogy: “Re-fetch or re-run a query when this parameter changes.”
3.3 No Dependency Array
If you don’t provide a dependency array, the effect runs after every render:
useEffect(() => {
console.log("Runs on every render!");
});
⚠️ Be careful — this can cause infinite loops if you update state inside the effect.
4. A Real Example: Fetching Groups on Page Load
This is exactly like your GroupList component:
useEffect(() => {
fetch("http://localhost:3000/groups", {
headers: {
Authorization: "Bearer TOKEN"
}
})
.then((res) => res.json())
.then((data) => setGroups(data.groups));
}, []); // empty array → run only once
- API is called once when component appears
-
groupsstate updates → React re-renders the UI automatically
5. Cleanup Function (Optional but Important)
Sometimes effects need cleanup, like:
- Removing event listeners
- Clearing timers
- Canceling subscriptions
useEffect(() => {
const timer = setInterval(() => console.log("Tick"), 1000);
// cleanup function
return () => clearInterval(timer);
}, []);
Think of it as undoing something before the component disappears, similar to closing a DB connection.
6. Common Beginner Mistakes
| Mistake | Why It Happens | How to Fix |
|---|---|---|
Forgetting [] when effect should run once |
Effect runs on every render → infinite API calls | Add empty dependency array []
|
| Updating state without dependency | Infinite loop: state changes → render → effect → state | Include correct dependencies [state] or move code to a button click |
Using useEffect for user actions |
e.g., clicking a button should not run automatically | Keep useEffect for side effects, not triggers |
7. Golden Rules
useEffect= side effects, not user actions- Empty array
[]= run once - Dependencies
[value]= run when value changes - Return a cleanup function if needed
- Don’t use
useEffectto replace normal function calls triggered by buttons
8. Quick Mental Model (Backend-Friendly)
| Backend Concept | React useEffect Equivalent |
|---|---|
| API request on page load | useEffect(() => fetchData(), []) |
| API request on parameter change | useEffect(() => fetchData(), [param]) |
| Closing DB connection | return () => cleanup() |
9. Summary
-
useEffectis React’s way of doing things after rendering -
Use it for:
- Fetching data
- Logging
- Timers or subscriptions
-
Don’t use it for:
- Button clicks
- User input triggers (use event handlers instead)
✅ Once you understand useEffect, React stops feeling magical — it becomes predictable, just like backend logic:
- Load component → run effect
- Dependencies change → re-run effect
- Cleanup when leaving → prevent leaks
Top comments (0)