React  

Why Does useEffect Run Multiple Times in React? Explained with Fixes

❓ Why Is My useEffect Running Multiple Times?

If you’ve noticed your useEffect firing more than once, even when your component mounts only once, you’re not alone. This is one of the most common issues new and experienced React developers run into.

Let’s look at the why, and more importantly — how to fix it.

🔁 Common Reasons useEffect Runs Multiple Times

1️⃣ Missing or Incorrect Dependency Array

If you don’t pass a second argument (dependency array) to useEffect, it will run after every render.

useEffect(() => { console.log("Runs after every render"); }); // no dependency array!

Fix: Add a proper dependency array.

useEffect(() => { console.log("Runs only once"); }, []); // runs only on mount

2️⃣ React Strict Mode in Development

If you're using React 18+ with <React.StrictMode>, React intentionally double-invokes certain lifecycle methods (including useEffect) in development mode only to help detect bugs.

// StrictMode is enabled by default in Create React App <React.StrictMode> <App /> </React.StrictMode>

Fix: This doesn’t affect production and is safe to ignore. To confirm, test without <StrictMode> or build the app for production.

3️⃣ Dependencies That Change on Every Render

If you include variables or objects/functions in the dependency array that change on every render, the effect will re-run.

const myObj = { name: "John" }; useEffect(() => { console.log("Runs every time because object reference changes"); }, [myObj]); // BAD

Fix: Memoize the value using useMemo, or refactor so the dependency is stable.

4️⃣ State Updates Causing Re-Renders

If you update a state inside useEffect without conditions, it may trigger another render, which causes the effect to re-run — leading to an infinite loop.

useEffect(() => { setCount(count + 1); // BAD: Causes infinite loop }, [count]);

Fix: Avoid directly updating state inside the effect unless it's properly guarded.

🧪 Best Practices to Control useEffect

Do This Instead of This
Use [] to run once on mount No dependency array
Memoize objects/functions Directly pass inline objects/functions
Handle async calls carefully Avoid async functions directly inside useEffect
Guard state updates Avoid uncontrolled loops inside useEffect

🧠 Pro Tip:

Use console logs to debug:

useEffect(() => { console.log("Effect fired"); }, [dependency]);

Also, use the React DevTools Profiler to track re-renders and useEffect calls.

✅ Conclusion

If your useEffect is running multiple times:

  • ✔️ Check your dependency array.

  • ✔️ Understand that React Strict Mode is double-invoking effects in dev only.

  • ✔️ Watch for changing references like objects and functions.

  • ✔️ Avoid state updates that cause infinite loops.

Once you understand how useEffect behaves, you can confidently use it to manage side effects without unexpected surprises.

Founded in 2003, Mindcracker is the authority in custom software development and innovation. We put best practices into action. We deliver solutions based on consumer and industry analysis.