React "Too Many Re-renders" and "Maximum Update Depth Exceeded": Fixes
Both errors mean a component keeps updating state, which re-renders it, which updates state again — forever. The four patterns that cause it (calling a handler instead of passing it, setState during render, effects without dependencies, objects in dependency arrays) and their fixes.
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Error: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect...
Both errors describe an infinite loop. In React, changing state makes the component render again. If rendering changes state, which makes it render, which changes state… React stops it before your browser tab freezes.
There are four common ways to cause it. Each has a one-line fix.
1. Calling a function instead of passing it
The most common cause by far:
<button onClick={setCount(count + 1)}>+</button> // ❌
The () calls setCount immediately, during render. That updates state, which re-renders, which calls it again.
You want to pass a function that React will call later, on click:
<button onClick={() => setCount(count + 1)}>+</button> // ✅
Same for any handler that takes an argument:
<button onClick={handleDelete(item.id)}>Delete</button> // ❌
<button onClick={() => handleDelete(item.id)}>Delete</button> // ✅
2. Setting state directly in the component body
function Profile({ user }) {
const [name, setName] = useState('')
setName(user.name) // ❌ runs on every render
...
}
Usually you don't need state at all — use the prop directly, or compute the value:
const name = user.name // ✅
If you genuinely need to reset state when a prop changes, give the component a key so React remounts it: <Profile key={user.id} user={user} />. (useState explained)
3. useEffect with no dependency array
useEffect(() => {
setItems(fetchedItems)
}) // ❌ no array: runs after every render
An effect with no dependency array runs after every render. If it sets state, that's a loop. Add the array:
useEffect(() => {
setItems(fetchedItems)
}, [fetchedItems]) // ✅ only when fetchedItems changes
And ask whether you need the effect at all — copying a prop into state inside an effect is usually unnecessary. (useEffect explained)
4. Objects or arrays in the dependency array
This one is sneaky, because the array is there:
const filters = { status: 'active' } // new object every render
useEffect(() => {
fetchItems(filters).then(setItems)
}, [filters]) // ❌ "changed" on every render
React compares dependencies by identity. A new object {} is never equal to the last one, even with the same contents. So the effect runs every render, sets state, re-renders, creates a new object…
Fixes:
// depend on the primitive value
useEffect(() => { ... }, [filters.status])
// or create the object once
const filters = useMemo(() => ({ status: 'active' }), [])
The same applies to functions defined in the component and passed as dependencies — wrap them in useCallback or move them inside the effect.
How to find which one it is
- The error's component stack in the console names the component. Start there.
- Look for
onClick={something(— an opening paren right after the handler name. - Look for
set...(calls outside of event handlers and effects. - Check every
useEffectthat calls a setter: does it have a dependency array, and does that array contain objects, arrays or functions?
The summary
- The loop is: state update → render → state update.
onClick={fn()}calls it;onClick={() => fn()}passes it.- Don't call setters in the component body.
- Give effects a dependency array, and keep objects and functions out of it (or memoise them).
EasySpawn gives Claude Code your running dev server and browser preview on a persistent machine, so it can reproduce render loops and verify the fix — not just guess at it. See how it works or join the waitlist.
Related: useEffect Explained · useState Explained · What Is React? · Next.js Hydration Errors
Keep reading
"Unexpected Token < in JSON at Position 0": What It Means and How to Fix It
Your code expected JSON and got HTML — almost always an error page or your app's index.html. Why it happens (wrong URL, 404, server error, SPA fallback, login redirect), how to see what the server actually sent, and how to parse responses safely.
"Each Child in a List Should Have a Unique Key Prop": What It Means
React's key warning appears when you render a list without telling React which item is which. Why keys matter, why array index is a bad key for lists that change, what to use instead, and how to fix the warning in fragments and nested maps.