React5 min read2026-03-01
React useEffect Infinite Loop
Diagnose and prevent infinite re-render loops caused by missing or mutating dependencies in useEffect.
Error Code / Stack Trace
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.Problem Overview
A React component triggers a state update inside useEffect, which re-renders the component, which in turn triggers useEffect again in an endless cycle.
Why Does This Happen?
- Updating a state variable inside useEffect that is also listed in its dependency array.
- Passing objects, functions, or arrays created inside the component body into the dependency array without useCallback/useMemo.
- Omitting the dependency array entirely (which causes the effect to run on every single render).
Step-by-Step Solution
Step 1: Use functional state updates
Avoid listing the updated state variable as a dependency by using the functional updater form.
tsx
// BAD (causes loop):
useEffect(() => {
setCount(count + 1);
}, [count]);
// GOOD (no count dependency needed):
useEffect(() => {
setCount((prev) => prev + 1);
}, []);Step 2: Memoize object and function dependencies
Wrap callback functions in useCallback so their object reference remains stable across renders.
tsx
const fetchUser = useCallback(async () => {
const res = await fetch(`/api/users/${userId}`);
const data = await res.json();
setUser(data);
}, [userId]);
useEffect(() => {
fetchUser();
}, [fetchUser]);Common Mistakes to Avoid
- •Disabling the react-hooks/exhaustive-deps eslint rule instead of fixing the unstable object reference.
Prevention & Best Practices
- Keep state primitive where possible and extract static functions outside the component function.
Frequently Asked Questions
Why do object dependencies trigger useEffect every time?
JavaScript compares objects by reference (===). In React, an object literal {} created inside a component has a new memory address on every render.
Related Developer Solutions & Tools
Recommended Tools
Related Error Fixes