@@ -13,7 +13,6 @@ import type {Lanes, Lane} from './ReactFiberLane.new';
13
13
import type { ReactPriorityLevel } from './ReactInternalTypes' ;
14
14
import type { Interaction } from 'scheduler/src/Tracing' ;
15
15
import type { SuspenseState } from './ReactFiberSuspenseComponent.new' ;
16
- import type { Effect as HookEffect } from './ReactFiberHooks.new' ;
17
16
import type { StackCursor } from './ReactFiberStack.new' ;
18
17
import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
19
18
@@ -122,8 +121,16 @@ import {
122
121
import { LegacyRoot } from './ReactRootTags' ;
123
122
import {
124
123
NoFlags ,
125
- PerformedWork ,
126
124
Placement ,
125
+ PassiveStatic ,
126
+ Incomplete ,
127
+ HostEffectMask ,
128
+ Hydrating ,
129
+ BeforeMutationMask ,
130
+ MutationMask ,
131
+ LayoutMask ,
132
+ PassiveMask ,
133
+ PerformedWork ,
127
134
Update ,
128
135
PlacementAndUpdate ,
129
136
Deletion ,
@@ -132,11 +139,6 @@ import {
132
139
ContentReset ,
133
140
Snapshot ,
134
141
Callback ,
135
- Passive ,
136
- PassiveStatic ,
137
- Incomplete ,
138
- HostEffectMask ,
139
- Hydrating ,
140
142
HydratingAndUpdate ,
141
143
StaticMask ,
142
144
} from './ReactFiberFlags' ;
@@ -1969,7 +1971,35 @@ function commitRootImpl(root, renderPriorityLevel) {
1969
1971
firstEffect = finishedWork . firstEffect ;
1970
1972
}
1971
1973
1972
- if ( firstEffect !== null ) {
1974
+ // If there are pending passive effects, schedule a callback to process them.
1975
+ // Do this as early as possible, so it is queued before anything else that
1976
+ // might get scheduled in the commit phase. (See #16714.)
1977
+ if (
1978
+ ( finishedWork . subtreeFlags & PassiveMask ) !== NoFlags ||
1979
+ ( finishedWork . flags & PassiveMask ) !== NoFlags
1980
+ ) {
1981
+ rootDoesHavePassiveEffects = true ;
1982
+ scheduleCallback ( NormalSchedulerPriority , ( ) => {
1983
+ flushPassiveEffects ( ) ;
1984
+ return null ;
1985
+ } ) ;
1986
+ }
1987
+
1988
+ // Check if there are any effects in the whole tree.
1989
+ // TODO: This is left over from the effect list implementation, where we had
1990
+ // to check for the existence of `firstEffect` to satsify Flow. I think the
1991
+ // only other reason this optimization exists is because it affects profiling.
1992
+ // Reconsider whether this is necessary.
1993
+ const subtreeHasEffects =
1994
+ ( finishedWork . subtreeFlags &
1995
+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
1996
+ NoFlags ;
1997
+ const rootHasEffect =
1998
+ ( finishedWork . flags &
1999
+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
2000
+ NoFlags ;
2001
+
2002
+ if ( subtreeHasEffects || rootHasEffect ) {
1973
2003
let previousLanePriority ;
1974
2004
if ( decoupleUpdatePriorityFromScheduler ) {
1975
2005
previousLanePriority = getCurrentUpdateLanePriority ( ) ;
@@ -2288,17 +2318,6 @@ function commitBeforeMutationEffects() {
2288
2318
2289
2319
resetCurrentDebugFiberInDEV ( ) ;
2290
2320
}
2291
- if ( ( flags & Passive ) !== NoFlags ) {
2292
- // If there are passive effects, schedule a callback to flush at
2293
- // the earliest opportunity.
2294
- if ( ! rootDoesHavePassiveEffects ) {
2295
- rootDoesHavePassiveEffects = true ;
2296
- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2297
- flushPassiveEffects ( ) ;
2298
- return null ;
2299
- } ) ;
2300
- }
2301
- }
2302
2321
nextEffect = nextEffect . nextEffect ;
2303
2322
}
2304
2323
}
@@ -2498,32 +2517,6 @@ export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
2498
2517
}
2499
2518
}
2500
2519
2501
- export function enqueuePendingPassiveHookEffectMount (
2502
- fiber : Fiber ,
2503
- effect : HookEffect ,
2504
- ) : void {
2505
- if ( ! rootDoesHavePassiveEffects ) {
2506
- rootDoesHavePassiveEffects = true ;
2507
- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2508
- flushPassiveEffects ( ) ;
2509
- return null ;
2510
- } ) ;
2511
- }
2512
- }
2513
-
2514
- export function enqueuePendingPassiveHookEffectUnmount (
2515
- fiber : Fiber ,
2516
- effect : HookEffect ,
2517
- ) : void {
2518
- if ( ! rootDoesHavePassiveEffects ) {
2519
- rootDoesHavePassiveEffects = true ;
2520
- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2521
- flushPassiveEffects ( ) ;
2522
- return null ;
2523
- } ) ;
2524
- }
2525
- }
2526
-
2527
2520
function flushPassiveEffectsImpl ( ) {
2528
2521
if ( rootWithPendingPassiveEffects === null ) {
2529
2522
return false ;
0 commit comments