Skip to content

Commit

Permalink
Schedule work to update Context.Consumer inside Suspense
Browse files Browse the repository at this point in the history
  • Loading branch information
okmttdhr committed May 8, 2021
1 parent fb36d98 commit 0c94041
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
67 changes: 67 additions & 0 deletions packages/react-reconciler/src/ReactFiberNewContext.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import type {SharedQueue} from './ReactUpdateQueue.new';
import {isPrimaryRenderer} from './ReactFiberHostConfig';
import {createCursor, push, pop} from './ReactFiberStack.new';
import {
ContextConsumer,
ContextProvider,
ClassComponent,
DehydratedFragment,
OffscreenComponent,
SuspenseComponent,
} from './ReactWorkTags';
import {
NoLanes,
Expand Down Expand Up @@ -157,6 +160,10 @@ export function scheduleWorkOnParentPath(
!isSubsetOfLanes(alternate.childLanes, renderLanes)
) {
alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
} else {
// Neither alternate was updated, which means the rest of the
// ancestor path already has sufficient priority.
break;
}
node = node.return;
}
Expand Down Expand Up @@ -361,6 +368,66 @@ function propagateContextChanges<T>(
}
scheduleWorkOnParentPath(consumer.return, renderLanes);

// If Context.Consumer is a descendant of Suspense,
// `scheduleWorkOnParentPath` may break before it get to Suspense.
// Schedule work to avoid bailout before Context.Consumer receives the value.
const contextConsumerIsDescendantOfSuspense =
workInProgress.tag === SuspenseComponent &&
workInProgress.child.tag === OffscreenComponent &&
consumer.tag === ContextConsumer;
if (contextConsumerIsDescendantOfSuspense) {
console.log(' contextConsumerWrappedBySuspense');
if (!isSubsetOfLanes(workInProgress.childLanes, renderLanes)) {
workInProgress.childLanes = mergeLanes(
workInProgress.childLanes,
renderLanes,
);
if (workInProgress.alternate !== null) {
workInProgress.alternate.childLanes = mergeLanes(
workInProgress.alternate.childLanes,
renderLanes,
);
}
} else if (
workInProgress.alternate !== null &&
!isSubsetOfLanes(
workInProgress.alternate.childLanes,
renderLanes,
)
) {
workInProgress.alternate.childLanes = mergeLanes(
workInProgress.alternate.childLanes,
renderLanes,
);
}
const primaryChildFragment = workInProgress.child;
if (
!isSubsetOfLanes(primaryChildFragment.childLanes, renderLanes)
) {
primaryChildFragment.childLanes = mergeLanes(
primaryChildFragment.childLanes,
renderLanes,
);
if (primaryChildFragment.alternate !== null) {
primaryChildFragment.alternate.childLanes = mergeLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
);
}
} else if (
primaryChildFragment.alternate !== null &&
!isSubsetOfLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
)
) {
primaryChildFragment.alternate.childLanes = mergeLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
);
}
}

if (!forcePropagateEntireTree) {
// During lazy propagation, when we find a match, we can defer
// propagating changes to the children, because we're going to
Expand Down
67 changes: 67 additions & 0 deletions packages/react-reconciler/src/ReactFiberNewContext.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import type {SharedQueue} from './ReactUpdateQueue.old';
import {isPrimaryRenderer} from './ReactFiberHostConfig';
import {createCursor, push, pop} from './ReactFiberStack.old';
import {
ContextConsumer,
ContextProvider,
ClassComponent,
DehydratedFragment,
OffscreenComponent,
SuspenseComponent,
} from './ReactWorkTags';
import {
NoLanes,
Expand Down Expand Up @@ -157,6 +160,10 @@ export function scheduleWorkOnParentPath(
!isSubsetOfLanes(alternate.childLanes, renderLanes)
) {
alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
} else {
// Neither alternate was updated, which means the rest of the
// ancestor path already has sufficient priority.
break;
}
node = node.return;
}
Expand Down Expand Up @@ -361,6 +368,66 @@ function propagateContextChanges<T>(
}
scheduleWorkOnParentPath(consumer.return, renderLanes);

// If Context.Consumer is a descendant of Suspense,
// `scheduleWorkOnParentPath` may break before it get to Suspense.
// Schedule work to avoid bailout before Context.Consumer receives the value.
const contextConsumerIsDescendantOfSuspense =
workInProgress.tag === SuspenseComponent &&
workInProgress.child.tag === OffscreenComponent &&
consumer.tag === ContextConsumer;
if (contextConsumerIsDescendantOfSuspense) {
console.log(' contextConsumerWrappedBySuspense');
if (!isSubsetOfLanes(workInProgress.childLanes, renderLanes)) {
workInProgress.childLanes = mergeLanes(
workInProgress.childLanes,
renderLanes,
);
if (workInProgress.alternate !== null) {
workInProgress.alternate.childLanes = mergeLanes(
workInProgress.alternate.childLanes,
renderLanes,
);
}
} else if (
workInProgress.alternate !== null &&
!isSubsetOfLanes(
workInProgress.alternate.childLanes,
renderLanes,
)
) {
workInProgress.alternate.childLanes = mergeLanes(
workInProgress.alternate.childLanes,
renderLanes,
);
}
const primaryChildFragment = workInProgress.child;
if (
!isSubsetOfLanes(primaryChildFragment.childLanes, renderLanes)
) {
primaryChildFragment.childLanes = mergeLanes(
primaryChildFragment.childLanes,
renderLanes,
);
if (primaryChildFragment.alternate !== null) {
primaryChildFragment.alternate.childLanes = mergeLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
);
}
} else if (
primaryChildFragment.alternate !== null &&
!isSubsetOfLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
)
) {
primaryChildFragment.alternate.childLanes = mergeLanes(
primaryChildFragment.alternate.childLanes,
renderLanes,
);
}
}

if (!forcePropagateEntireTree) {
// During lazy propagation, when we find a match, we can defer
// propagating changes to the children, because we're going to
Expand Down

0 comments on commit 0c94041

Please sign in to comment.