diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 2251dac255ef..a059f50ccaa9 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -199,14 +199,13 @@ const { type ExecutionContext = number; -const NoContext = /* */ 0b0000000; -const BatchedContext = /* */ 0b0000001; -const EventContext = /* */ 0b0000010; -const DiscreteEventContext = /* */ 0b0000100; -const LegacyUnbatchedContext = /* */ 0b0001000; -const RenderContext = /* */ 0b0010000; -const CommitContext = /* */ 0b0100000; -const PassiveEffectContext = /* */ 0b1000000; +const NoContext = /* */ 0b000000; +const BatchedContext = /* */ 0b000001; +const EventContext = /* */ 0b000010; +const DiscreteEventContext = /* */ 0b000100; +const LegacyUnbatchedContext = /* */ 0b001000; +const RenderContext = /* */ 0b010000; +const CommitContext = /* */ 0b100000; type RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5; const RootIncomplete = 0; @@ -299,6 +298,10 @@ let spawnedWorkDuringRender: null | Array = null; // receive the same expiration time. Otherwise we get tearing. let currentEventTime: ExpirationTime = NoWork; +// Dev only flag that tracks if passive effects are currently being flushed. +// We warn about state updates for unmounted components differently in this case. +let isFlushingPassiveEffects = false; + export function getWorkInProgressRoot(): FiberRoot | null { return workInProgressRoot; } @@ -2273,6 +2276,10 @@ function flushPassiveEffectsImpl() { return false; } + if (__DEV__) { + isFlushingPassiveEffects = true; + } + const root = rootWithPendingPassiveEffects; const expirationTime = pendingPassiveEffectsExpirationTime; rootWithPendingPassiveEffects = null; @@ -2284,7 +2291,6 @@ function flushPassiveEffectsImpl() { ); const prevExecutionContext = executionContext; executionContext |= CommitContext; - executionContext |= PassiveEffectContext; const prevInteractions = pushInteractions(root); if (runAllPassiveEffectDestroysBeforeCreates) { @@ -2448,6 +2454,10 @@ function flushPassiveEffectsImpl() { nestedPassiveUpdateCount = rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; + if (__DEV__) { + isFlushingPassiveEffects = false; + } + return true; } @@ -2816,7 +2826,7 @@ function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { } // If we are currently flushing passive effects, change the warning text. - if ((executionContext & PassiveEffectContext) !== NoContext) { + if (isFlushingPassiveEffects) { console.error( "Can't perform a React state update from within a useEffect cleanup function. " + 'To fix, move state updates to the useEffect() body in %s.%s',