Why does my React useEffect keep running in an infinite loop — and how do I fix it properly?
If you’ve worked with React long enough, you’ve probably run into this error:
Or you just notice your useEffect keeps firing over and over again — sometimes even calling APIs endlessly.
Let’s break down why this happens and how to fix it cleanly.
🔍 First: How useEffect Actually Works
Basic form:
The dependency array controls when it runs.
| Dependency Array | Effect Runs |
|---|---|
[] | Once after mount |
[value] | Every time value changes |
| No array | On every render |
Most infinite loops happen because we update state inside useEffect — which triggers a re-render — which triggers the effect again.
❌ Problem 1 — Updating State Inside useEffect With That State as Dependency
Example:
What happens?
-
count = 0
-
effect runs → setCount(1)
-
count updates → triggers effect again
-
setCount(2)
-
repeat forever 🚨
✅ Fix: Remove State From Dependency or Refactor Logic
If you only want to run once:
Or better: update directly where needed — not in an effect unless necessary.
❌ Problem 2 — Fetching Data and Setting State Incorrectly
Beginner code often looks like this:
Because users is in the dependency array, it updates every time users changes → infinite API calls.
✅ Fix: Remove users From Dependencies
❌ Problem 3 — Objects/Arrays as Dependencies (They Change Every Render)
Example:
Even if the values are same, a new object is created every render, so useEffect keeps firing.
✅ Fix: Memoize It
Now React sees the same object.
❌ Problem 4 — Functions as Dependencies
Same issue — functions are recreated every render.
✅ Fix: Wrap The Function in useCallback
❌ Problem 5 — Missing Dependency (Looks Fixed But Actually Wrong)
Sometimes people do this:
This “fixes” the loop, but now the effect won’t update when value changes — which may be a bug.
Better approach: depend only on what matters and ensure no unnecessary state updates.
🧪 Common Real-World Pattern — API Call + Loading State
Here’s a safe pattern:
✔ runs once
✔ no infinite loop
✔ clean UI handling
🔁 Why Does useEffect Run Twice in Dev Mode?
In React Strict Mode (development only), React intentionally calls effects twice to detect unsafe code.
This is normal in dev.
It does not happen in production.
🧠 Golden Rules To Avoid Loops
✔ Never update state that lives in the dependency list
✔ Memoize objects/functions used in dependencies
✔ Fetch data with [] unless filters change
✔ Understand that render → effect → render is normal
✔ Only put necessary values in the dependency array
🏁 Final Thoughts
useEffect isn’t broken.
It’s just honest — it runs whenever something it depends on changes.
Once you understand:
👉 “State change → re-render → effect runs based on dependencies”
…the bugs suddenly become predictable — and easy to fix.