Tutorials Logic, IN info@tutorialslogic.com

Maximum update depth exceeded in React Fix: Tutorial, Examples, FAQs & Interview Tips

What is This Error?

The "Maximum update depth exceeded" error occurs when React detects a component is stuck in an infinite update loop. This typically happens when useEffect or componentDidUpdate triggers a state update that causes a re-render, which triggers the effect again "” endlessly.

Common Causes

  • useEffect with no dependency array that sets state unconditionally
  • useEffect dependency includes an object/array that's recreated every render
  • setState called inside useEffect that depends on the state being set
  • Parent and child components updating each other's state in a cycle
  • Callback prop recreated on every render causing child useEffect to loop

Quick Fix (TL;DR)

Quick Solution

Quick Solution
// ❌ Problem "” no dependency array, infinite loop
useEffect(() => {
  setCount(count + 1); // Sets state → re-render → effect runs again
});

// ✅ Solution 1 "” empty array, runs once
useEffect(() => {
  setCount(1);
}, []);

// ✅ Solution 2 "” functional update, no dependency needed
useEffect(() => {
  setCount(prev => prev + 1);
}, []); // Only runs on mount

Common Scenarios & Solutions

Problem

Problem
function Timer() {
  const [time, setTime] = useState(0);

  // ❌ No dependency array "” runs after every render
  useEffect(() => {
    setTime(time + 1); // Sets state → re-render → effect runs → infinite!
  });

  return <div>{time}</div>;
}

Solution

Solution
function Timer() {
  const [time, setTime] = useState(0);

  // ✅ Use setInterval with cleanup
  useEffect(() => {
    const interval = setInterval(() => {
      setTime(prev => prev + 1); // Functional update "” no dependency needed
    }, 1000);
    return () => clearInterval(interval); // Cleanup
  }, []); // Empty array "” runs once on mount

  return <div>{time}</div>;
}

Problem

Problem
function Search({ query }) {
  const [results, setResults] = useState([]);
  const filters = { query, page: 1 }; // ❌ New object every render!

  useEffect(() => {
    fetchResults(filters).then(setResults);
  }, [filters]); // filters changes every render → infinite loop!
}

Solution

Solution
function Search({ query }) {
  const [results, setResults] = useState([]);

  // ✅ Use primitive values as dependencies
  useEffect(() => {
    fetchResults({ query, page: 1 }).then(setResults);
  }, [query]); // Only re-run when query string changes
}

// ✅ Or memoize the object
const filters = useMemo(() => ({ query, page: 1 }), [query]);

Problem

Problem
function Parent() {
  const [data, setData] = useState(null);

  // ❌ New function reference every render
  const onLoad = (result) => setData(result);

  return <Child onLoad={onLoad} />;
}

function Child({ onLoad }) {
  useEffect(() => {
    fetchData().then(onLoad);
  }, [onLoad]); // onLoad changes every render → infinite loop!
}

Solution

Solution
function Parent() {
  const [data, setData] = useState(null);

  // ✅ Stable reference with useCallback
  const onLoad = useCallback((result) => setData(result), []);

  return <Child onLoad={onLoad} />;
}

Problem

Problem
const [items, setItems] = useState([]);

// ❌ items in deps + setItems → infinite loop
useEffect(() => {
  setItems([...items, newItem]);
}, [items]);

Solution

Solution
// ✅ Use functional update "” no need to list items as dependency
useEffect(() => {
  setItems(prev => [...prev, newItem]);
}, [newItem]); // Only depends on newItem

Best Practices to Avoid This Error

  • Always add dependency arrays to useEffect - Never omit them
  • Use functional state updates - setState(prev => ...) avoids needing state in deps
  • Use primitive values as dependencies - Avoid objects and arrays
  • Memoize objects with useMemo - Stable references for complex deps
  • Memoize callbacks with useCallback - Stable function references
  • Add conditions before setState in effects - Only update when value actually changes
  • Use eslint-plugin-react-hooks - Warns about missing or incorrect dependencies

Related Errors

Frequently Asked Questions

This error occurs when useEffect triggers a state update that causes a re-render, which triggers the effect again, creating an infinite loop. Common causes: no dependency array, objects in deps, or state that depends on itself.

"Too many re-renders" usually means setState is called during the render phase. "Maximum update depth exceeded" means useEffect is causing an infinite update cycle after rendering.

Objects are compared by reference in JavaScript. A new object {} !== {} even with identical content. So React sees the dependency as changed on every render, re-running the effect endlessly.

Instead of setCount(count + 1), use setCount(prev => prev + 1). This reads the latest state without needing count in the dependency array, breaking the loop.

Add console.log inside the effect to count how many times it runs. Check the dependency array for objects/arrays. Use React DevTools Profiler to see which component is re-rendering excessively.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.