react runtime_error ai_generated true

Warning: A stale closure was detected. The callback passed to useEffect references a variable that may be outdated.

ID: react/stale-closure-useeffect

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

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
React 16.8.0 active
React 17.0.2 active
React 18.2.0 active

Root Cause

A useEffect callback captures a variable from an earlier render, and when that variable changes, the effect still uses the old value because the dependency array is missing or incomplete.

generic

中文

useEffect 回调捕获了来自之前渲染的变量,当该变量发生变化时,由于依赖数组缺失或不完整,effect 仍然使用旧值。

Official Documentation

https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

Workarounds

  1. 90% success Add all variables referenced inside the effect to the dependency array: `useEffect(() => { console.log(count); }, [count]);`
    Add all variables referenced inside the effect to the dependency array: `useEffect(() => { console.log(count); }, [count]);`
  2. 85% success Use the functional update form of setState or useReducer if the stale variable is a state value: `setCount(prev => prev + 1)`
    Use the functional update form of setState or useReducer if the stale variable is a state value: `setCount(prev => prev + 1)`
  3. 80% success Use `useRef` to hold the latest value and update it via an effect: `const countRef = useRef(count); countRef.current = count;` then access `countRef.current` inside the effect.
    Use `useRef` to hold the latest value and update it via an effect: `const countRef = useRef(count); countRef.current = count;` then access `countRef.current` inside the effect.

中文步骤

  1. Add all variables referenced inside the effect to the dependency array: `useEffect(() => { console.log(count); }, [count]);`
  2. Use the functional update form of setState or useReducer if the stale variable is a state value: `setCount(prev => prev + 1)`
  3. Use `useRef` to hold the latest value and update it via an effect: `const countRef = useRef(count); countRef.current = count;` then access `countRef.current` inside the effect.

Dead Ends

Common approaches that don't work:

  1. 80% fail

    The effect never re-runs when the captured variable changes, so the closure remains stale indefinitely.

  2. 75% fail

    The variable is still captured at the time of effect creation; if it changes, the effect still uses the old value.

  3. 60% fail

    If the ref is not manually updated when the variable changes, it still holds the old value.