Skip to content

Commit d8d34b8

Browse files
committed
Extract state and context check to separate function
The only reason we pass `updateLanes` to some begin functions is to check if we can perform an early bail out. But this is also available as `current.lanes`, so we can read it from there instead. I think the only reason we didn't do it this way originally is because components that have two phases — error and Suspense boundaries — use `workInProgress.lanes` to prevent a bail out, since during the initial render there is no `current`. But we can check the `DidCapture` flag instead, which we use elsewhere to detect the second phase.
1 parent 423d6f5 commit d8d34b8

File tree

4 files changed

+98
-72
lines changed

4 files changed

+98
-72
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.new.js

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ function updateMemoComponent(
409409
workInProgress: Fiber,
410410
Component: any,
411411
nextProps: any,
412-
updateLanes: Lanes,
413412
renderLanes: Lanes,
414413
): null | Fiber {
415414
if (current === null) {
@@ -437,7 +436,6 @@ function updateMemoComponent(
437436
workInProgress,
438437
resolvedType,
439438
nextProps,
440-
updateLanes,
441439
renderLanes,
442440
);
443441
}
@@ -482,7 +480,11 @@ function updateMemoComponent(
482480
}
483481
}
484482
const currentChild = ((current.child: any): Fiber); // This is always exactly one child
485-
if (!includesSomeLane(updateLanes, renderLanes)) {
483+
const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
484+
current,
485+
renderLanes,
486+
);
487+
if (!hasScheduledUpdateOrContext) {
486488
// This will be the props with resolved defaultProps,
487489
// unlike current.memoizedProps which will be the unresolved ones.
488490
const prevProps = currentChild.memoizedProps;
@@ -507,7 +509,6 @@ function updateSimpleMemoComponent(
507509
workInProgress: Fiber,
508510
Component: any,
509511
nextProps: any,
510-
updateLanes: Lanes,
511512
renderLanes: Lanes,
512513
): null | Fiber {
513514
// TODO: current can be non-null here even if the component
@@ -553,7 +554,7 @@ function updateSimpleMemoComponent(
553554
(__DEV__ ? workInProgress.type === current.type : true)
554555
) {
555556
didReceiveUpdate = false;
556-
if (!includesSomeLane(renderLanes, updateLanes)) {
557+
if (!checkScheduledUpdateOrContext(current, renderLanes)) {
557558
// The pending lanes were cleared at the beginning of beginWork. We're
558559
// about to bail out, but there might be other lanes that weren't
559560
// included in the current render. Usually, the priority level of the
@@ -740,7 +741,6 @@ const updateLegacyHiddenComponent = updateOffscreenComponent;
740741
function updateCacheComponent(
741742
current: Fiber | null,
742743
workInProgress: Fiber,
743-
updateLanes: Lanes,
744744
renderLanes: Lanes,
745745
) {
746746
if (!enableCache) {
@@ -762,7 +762,7 @@ function updateCacheComponent(
762762
pushCacheProvider(workInProgress, freshCache);
763763
} else {
764764
// Check for updates
765-
if (includesSomeLane(renderLanes, updateLanes)) {
765+
if (includesSomeLane(current.lanes, renderLanes)) {
766766
cloneUpdateQueue(current, workInProgress);
767767
processUpdateQueue(workInProgress, null, null, renderLanes);
768768
}
@@ -1306,7 +1306,6 @@ function mountLazyComponent(
13061306
_current,
13071307
workInProgress,
13081308
elementType,
1309-
updateLanes,
13101309
renderLanes,
13111310
) {
13121311
if (_current !== null) {
@@ -1396,7 +1395,6 @@ function mountLazyComponent(
13961395
workInProgress,
13971396
Component,
13981397
resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too
1399-
updateLanes,
14001398
renderLanes,
14011399
);
14021400
return child;
@@ -3214,6 +3212,27 @@ function remountFiber(
32143212
}
32153213
}
32163214

3215+
function checkScheduledUpdateOrContext(
3216+
current: Fiber,
3217+
renderLanes: Lanes,
3218+
): boolean {
3219+
// Before performing an early bailout, we must check if there are pending
3220+
// updates or context.
3221+
const updateLanes = current.lanes;
3222+
if (includesSomeLane(updateLanes, renderLanes)) {
3223+
return true;
3224+
}
3225+
// No pending update, but because context is propagated lazily, we need
3226+
// to check for a context change before we bail out.
3227+
if (enableLazyContextPropagation) {
3228+
const dependencies = current.dependencies;
3229+
if (dependencies !== null && checkIfContextChanged(dependencies)) {
3230+
return true;
3231+
}
3232+
}
3233+
return false;
3234+
}
3235+
32173236
function attemptEarlyBailoutIfNoScheduledUpdate(
32183237
current: Fiber,
32193238
workInProgress: Fiber,
@@ -3428,8 +3447,6 @@ function beginWork(
34283447
workInProgress: Fiber,
34293448
renderLanes: Lanes,
34303449
): Fiber | null {
3431-
let updateLanes = workInProgress.lanes;
3432-
34333450
if (__DEV__) {
34343451
if (workInProgress._debugNeedsRemount && current !== null) {
34353452
// This will restart the begin phase with a new fiber.
@@ -3449,17 +3466,6 @@ function beginWork(
34493466
}
34503467

34513468
if (current !== null) {
3452-
// TODO: The factoring of this block is weird.
3453-
if (
3454-
enableLazyContextPropagation &&
3455-
!includesSomeLane(renderLanes, updateLanes)
3456-
) {
3457-
const dependencies = current.dependencies;
3458-
if (dependencies !== null && checkIfContextChanged(dependencies)) {
3459-
updateLanes = mergeLanes(updateLanes, renderLanes);
3460-
}
3461-
}
3462-
34633469
const oldProps = current.memoizedProps;
34643470
const newProps = workInProgress.pendingProps;
34653471

@@ -3472,14 +3478,27 @@ function beginWork(
34723478
// If props or context changed, mark the fiber as having performed work.
34733479
// This may be unset if the props are determined to be equal later (memo).
34743480
didReceiveUpdate = true;
3475-
} else if (!includesSomeLane(renderLanes, updateLanes)) {
3476-
didReceiveUpdate = false;
3477-
return attemptEarlyBailoutIfNoScheduledUpdate(
3481+
} else {
3482+
// Neither props nor legacy context changes. Check if there's a pending
3483+
// update or context change.
3484+
const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
34783485
current,
3479-
workInProgress,
34803486
renderLanes,
34813487
);
3482-
} else {
3488+
if (
3489+
!hasScheduledUpdateOrContext &&
3490+
// If this is the second pass of an error or suspense boundary, there
3491+
// may not be work scheduled on `current`, so we check for this flag.
3492+
(workInProgress.flags & DidCapture) === NoFlags
3493+
) {
3494+
// No pending updates or context. Bail out now.
3495+
didReceiveUpdate = false;
3496+
return attemptEarlyBailoutIfNoScheduledUpdate(
3497+
current,
3498+
workInProgress,
3499+
renderLanes,
3500+
);
3501+
}
34833502
if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
34843503
// This is a special case that only exists for legacy mode.
34853504
// See https://github.com/facebook/react/pull/19216.
@@ -3518,7 +3537,6 @@ function beginWork(
35183537
current,
35193538
workInProgress,
35203539
elementType,
3521-
updateLanes,
35223540
renderLanes,
35233541
);
35243542
}
@@ -3611,7 +3629,6 @@ function beginWork(
36113629
workInProgress,
36123630
type,
36133631
resolvedProps,
3614-
updateLanes,
36153632
renderLanes,
36163633
);
36173634
}
@@ -3621,7 +3638,6 @@ function beginWork(
36213638
workInProgress,
36223639
workInProgress.type,
36233640
workInProgress.pendingProps,
3624-
updateLanes,
36253641
renderLanes,
36263642
);
36273643
}
@@ -3657,12 +3673,7 @@ function beginWork(
36573673
}
36583674
case CacheComponent: {
36593675
if (enableCache) {
3660-
return updateCacheComponent(
3661-
current,
3662-
workInProgress,
3663-
updateLanes,
3664-
renderLanes,
3665-
);
3676+
return updateCacheComponent(current, workInProgress, renderLanes);
36663677
}
36673678
break;
36683679
}

0 commit comments

Comments
 (0)