react runtime_error ai_generated true

Error: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect without a dependency array

ID: react/maximum-update-depth-exceeded-useeffect

Also available as: JSON · Markdown · 中文
95%Fix Rate
90%Confidence
1Evidence
2023-01-10First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
React 16.8+ active
React 17 active
React 18 active
React 19 active

Root Cause

A useEffect calls setState without specifying dependencies, causing an infinite loop of render → effect → setState → render.

generic

中文

useEffect 调用 setState 时未指定依赖项,导致渲染 → 副作用 → setState → 渲染的无限循环。

Official Documentation

https://react.dev/reference/react/useEffect

Workarounds

  1. 95% success Add a dependency array to useEffect with the values that should trigger the effect: useEffect(() => { setCount(count + 1); }, [count]); // Now it only runs when count changes, avoiding infinite loop if count is not updated in a way that causes re-render
    Add a dependency array to useEffect with the values that should trigger the effect:
    
    useEffect(() => {
      setCount(count + 1);
    }, [count]); // Now it only runs when count changes, avoiding infinite loop if count is not updated in a way that causes re-render
  2. 90% success Use the functional update form of setState and an empty dependency array if the effect should run only once: useEffect(() => { setCount(prev => prev + 1); }, []); // Runs once on mount
    Use the functional update form of setState and an empty dependency array if the effect should run only once:
    
    useEffect(() => {
      setCount(prev => prev + 1);
    }, []); // Runs once on mount
  3. 85% success If the effect depends on props or state that change, use useReducer to manage complex state transitions and avoid direct setState in effects.
    If the effect depends on props or state that change, use useReducer to manage complex state transitions and avoid direct setState in effects.

中文步骤

  1. Add a dependency array to useEffect with the values that should trigger the effect:
    
    useEffect(() => {
      setCount(count + 1);
    }, [count]); // Now it only runs when count changes, avoiding infinite loop if count is not updated in a way that causes re-render
  2. Use the functional update form of setState and an empty dependency array if the effect should run only once:
    
    useEffect(() => {
      setCount(prev => prev + 1);
    }, []); // Runs once on mount
  3. If the effect depends on props or state that change, use useReducer to manage complex state transitions and avoid direct setState in effects.

Dead Ends

Common approaches that don't work:

  1. 80% fail

    Does not address the root cause; the useEffect still runs without dependencies, triggering setState on every render.

  2. 90% fail

    Causes an infinite loop during render because setState triggers a re-render immediately.

  3. 70% fail

    The condition may still be true on every render, or the effect runs on every render anyway, leading to the same loop.