Maximum Update Depth Exceeded in React
useEffect Infinite Loop Complete Fix
React 19 • Next.js 15 • TypeScript • Vite • React Router • Redux Toolkit
🌀 What Is the “Maximum Update Depth Exceeded” Error?
The “Maximum update depth exceeded” error is a close cousin
of the "Too many re-renders" error. It occurs when a React component repeatedly
triggers state updates in a loop, typically caused by a useEffect
hook that updates state without properly managing its dependencies.
The full error message reads:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or useEffect.
React limits the number of nested updates to prevent infinite loops.
This error is specifically tied to useEffect and
lifecycle methods that run after render. While the "Too many re-renders"
error often comes from setState in the render body, this error
comes from setState inside useEffect or other
post-render lifecycle methods.
⚡ Quick Reference — Common Causes at a Glance
🧩 Detailed Breakdown — Every Cause Solved
Each card below dives deep into one specific cause of the "Maximum update depth exceeded" error, with root causes, code examples, and step-by-step fixes.
🛡️ Prevention — Avoid useEffect Infinite Loops
Never omit the dependency array. Use
[] for effects that should run only once.
Wrap functions used in
useEffect dependencies with useCallback.
Memoize objects and arrays that are used as dependencies to prevent unnecessary re-renders.
When updating state based on previous state, use the functional form:
setState(prev => prev + 1).
Always check if the state has actually changed before dispatching in
useEffect.
❓ Frequently Asked Questions
Both errors indicate infinite loops, but they come from different sources:
- "Too many re-renders" — caused by
setStatecalled directly in the render body. - "Maximum update depth exceeded" — caused by
setStatecalled insideuseEffector other post-render lifecycle methods.
Both errors have the same root cause: a state update that triggers another state update in a loop.
React enforces a limit of 50 nested updates in development and around 150 in production. This prevents infinite loops from crashing the browser.
When you hit this limit, React throws the "Maximum update depth exceeded" error.
No. The update depth limit remains the same in React 19.
React's concurrent features (like useTransition and Suspense)
don't affect this limit — they help with rendering performance but don't
prevent infinite loops.
Best practices for debugging:
- Add console logs — log inside
useEffectto see how often it runs. - Use React DevTools — the "Profiler" tab can show render frequency.
- Check your dependency array — missing or incorrect dependencies are the #1 cause.
- Log dependency values — log each dependency to see if they change unexpectedly.
- Use the React DevTools "Highlight updates" — visually see which components are re-rendering.
Yes. Common Redux-related causes include:
- Dispatching actions inside
useEffectthat update the same state the effect depends on. - Using
useSelectorwith a selector that returns a new object every time. - Using
useDispatchinsideuseEffectwithout proper dependencies.
Fix: Use shallowEqual from react-redux
or memoize selectors with reselect or createSelector.
// ✅ Use memoized selectors
import { createSelector } from '@reduxjs/toolkit';
const selectUser = createSelector(
state => state.user,
user => user
);
Yes. Using useRouter inside useEffect
without proper dependencies can cause infinite loops.
// ❌ Wrong — router.push in useEffect with no deps
function MyComponent() {
const router = useRouter();
useEffect(() => {
router.push('/dashboard'); // 💥 Infinite loop!
}); // 👈 No dependency array
return <div>Redirecting...</div>;
}
// ✅ Correct — with dependency array
function MyComponent() {
const router = useRouter();
useEffect(() => {
router.push('/dashboard');
}, [router]); // 👈 router is stable
return <div>Redirecting...</div>;
}

0 Comments
thanks for your comments!