Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.
ID: react/warning-unstable-flushdiscrete-updates
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| React 18.2.0 | active | — | — | — |
| React 18.3.0-canary | active | — | — | — |
| React 19.0.0-rc | active | — | — | — |
Root Cause
React's internal scheduling mechanism detects a recursive state update during rendering, often caused by calling setState in a useEffect without proper dependencies, or by using synchronous event handlers that trigger state updates during the render phase.
generic中文
React 的内部调度机制检测到渲染期间发生递归状态更新,通常是由于在 useEffect 中调用 setState 而没有正确的依赖项,或者使用同步事件处理器在渲染阶段触发状态更新。
Official Documentation
https://react.dev/reference/react/useEffectWorkarounds
-
85% success Review and fix useEffect dependencies: ensure state updates are not triggered inside the effect itself without proper memoization. Example: useEffect(() => { setCount(prev => prev + 1); }, []); // Only on mount, not on every render
Review and fix useEffect dependencies: ensure state updates are not triggered inside the effect itself without proper memoization. Example: useEffect(() => { setCount(prev => prev + 1); }, []); // Only on mount, not on every render -
80% success Use useReducer instead of useState for complex state logic to avoid accidental recursion. Example: const [state, dispatch] = useReducer(reducer, initialState);
Use useReducer instead of useState for complex state logic to avoid accidental recursion. Example: const [state, dispatch] = useReducer(reducer, initialState);
-
90% success Wrap state updates in event handlers (e.g., onClick) rather than in the render phase or useEffect without dependencies. Ensure the update is triggered by user interaction, not during render.
Wrap state updates in event handlers (e.g., onClick) rather than in the render phase or useEffect without dependencies. Ensure the update is triggered by user interaction, not during render.
中文步骤
Review and fix useEffect dependencies: ensure state updates are not triggered inside the effect itself without proper memoization. Example: useEffect(() => { setCount(prev => prev + 1); }, []); // Only on mount, not on every renderUse useReducer instead of useState for complex state logic to avoid accidental recursion. Example: const [state, dispatch] = useReducer(reducer, initialState);
Wrap state updates in event handlers (e.g., onClick) rather than in the render phase or useEffect without dependencies. Ensure the update is triggered by user interaction, not during render.
Dead Ends
Common approaches that don't work:
-
Add a setTimeout around the setState call to delay the update
70% fail
This masks the issue but doesn't fix the root cause; the state update may still cause a re-render loop and degrade performance.
-
Use ReactDOM.flushSync to force synchronous updates
85% fail
flushSync is meant for specific use cases and can actually trigger the same warning if called during rendering.
-
Ignore the warning as it's only in development mode
90% fail
The warning indicates a real issue that can cause infinite loops or UI inconsistencies in production.