@@ -160,7 +160,6 @@ import {
160
160
import getComponentName from 'shared/getComponentName' ;
161
161
import ReactStrictModeWarnings from './ReactStrictModeWarnings' ;
162
162
import {
163
- current as currentDebugFiberInDEV ,
164
163
isRendering as ReactCurrentDebugFiberIsRenderingInDEV ,
165
164
resetCurrentFiber as resetCurrentDebugFiberInDEV ,
166
165
setCurrentFiber as setCurrentDebugFiberInDEV ,
@@ -2736,38 +2735,20 @@ function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {
2736
2735
didWarnStateUpdateForUnmountedComponent = new Set ( [ componentName ] ) ;
2737
2736
}
2738
2737
2739
- // If we are currently flushing passive effects, change the warning text.
2740
2738
if ( isFlushingPassiveEffects ) {
2739
+ // Do not warn if we are currently flushing passive effects!
2740
+ //
2741
2741
// React can't directly detect a memory leak, but there are some clues that warn about one.
2742
2742
// One of these clues is when an unmounted React component tries to update its state.
2743
2743
// For example, if a component forgets to remove an event listener when unmounting,
2744
- // that listener may be called later and try to update state, at which point React would warn about the potential leak.
2745
- //
2746
- // Warning signals like this are more useful if they're strong.
2747
- // For this reason, it's good to always avoid updating state from inside of an effect's cleanup function.
2748
- // Even when you know there is no potential leak, React has no way to know and so it will warn anyway.
2749
- // In most cases we suggest moving state updates to the useEffect() body instead.
2750
- // This works so long as the component is updating its own state (or the state of a descendant).
2744
+ // that listener may be called later and try to update state,
2745
+ // at which point React would warn about the potential leak.
2751
2746
//
2752
- // However this will not work when a component updates its parent state in a cleanup function.
2753
- // If such a component is unmounted but its parent remains mounted, the state will be out of sync.
2754
- // For this reason, we avoid showing the warning if a component is updating an ancestor.
2755
- let currentTargetFiber = fiber ;
2756
- while ( currentTargetFiber !== null ) {
2757
- // currentDebugFiberInDEV owns the effect destroy function currently being invoked.
2758
- if (
2759
- currentDebugFiberInDEV === currentTargetFiber ||
2760
- currentDebugFiberInDEV === currentTargetFiber . alternate
2761
- ) {
2762
- console . error (
2763
- "Can't perform a React state update from within a useEffect cleanup function. " +
2764
- 'To fix, move state updates to the useEffect() body.%s' ,
2765
- getStackByFiberInDevAndProd ( ( ( currentDebugFiberInDEV : any ) : Fiber ) ) ,
2766
- ) ;
2767
- break ;
2768
- }
2769
- currentTargetFiber = currentTargetFiber . return ;
2770
- }
2747
+ // Warning signals are the most useful when they're strong.
2748
+ // (So we should avoid false positive warnings.)
2749
+ // Updating state from within an effect cleanup function is sometimes a necessary pattern, e.g.:
2750
+ // 1. Updating an ancestor that a component had registered itself with on mount.
2751
+ // 2. Resetting state when a component is hidden after going offscreen.
2771
2752
} else {
2772
2753
console . error (
2773
2754
"Can't perform a React state update on an unmounted component. This " +
0 commit comments