27
enableProfilerCommitHooks,
28
enableSchedulerTracing,
29
warnAboutUnmockedScheduler,
30
+ deferRenderPhaseUpdateToNextBatch,
31
} from 'shared/ReactFeatureFlags';
32
import ReactSharedInternals from 'shared/ReactSharedInternals';
33
import invariant from 'shared/invariant';
124
isSubsetOfLanes,
125
mergeLanes,
126
removeLanes,
127
+ pickArbitraryLane,
128
hasDiscreteLanes,
129
hasUpdatePriority,
130
getNextLanes,
356
return getCurrentPriorityLevel() === ImmediateSchedulerPriority
357
? (SyncLane: Lane)
358
: (SyncBatchedLane: Lane);
359
+ } else if (
360
+ !deferRenderPhaseUpdateToNextBatch &&
361
+ (executionContext & RenderContext) !== NoContext &&
362
+ workInProgressRootRenderLanes !== NoLanes
363
+ ) {
364
+ // This is a render phase update. These are not officially supported. The
365
+ // old behavior is to give this the same "thread" (expiration time) as
366
+ // whatever is currently rendering. So if you call `setState` on a component
367
+ // that happens later in the same render, it will flush. Ideally, we want to
368
+ // remove the special case and treat them as if they came from an
369
+ // interleaved event. Regardless, this pattern is not officially supported.
370
+ // This behavior is only a fallback. The flag only exists until we can roll
371
+ // out the setState warnning, since existing code might accidentally rely on
372
+ // the current behavior.
373
+ return pickArbitraryLane(workInProgressRootRenderLanes);
374
}
375
376
// The algorithm for assigning an update to a lane should be stable for all
559
markRootUpdated(root, lane);
560
if (workInProgressRoot === root) {
561
// Received an update to a tree that's in the middle of rendering. Mark
545
- // that there is unprocessed work on this root.
546
- workInProgressRootUpdatedLanes = mergeLanes(
547
- workInProgressRootUpdatedLanes,
548
- lane,
549
- );
562
+ // that there was an interleaved update work on this root. Unless the
563
+ // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render
564
+ // phase update. In that case, we don't treat render phase updates as if
565
+ // they were interleaved, for backwards compat reasons.
566
+ if (
567
+ deferRenderPhaseUpdateToNextBatch ||
568
+ (executionContext & RenderContext) === NoContext
569
+ ) {
570
+ workInProgressRootUpdatedLanes = mergeLanes(
571
+ workInProgressRootUpdatedLanes,
572
+ lane,
573
+ );
574
+ }
575
if (workInProgressRootExitStatus === RootSuspendedWithDelay) {
576
// The root already suspended with a delay, which means this render
577
// definitely won't finish. Since we have a new update, let's mark it as