Skip to content

Commit aea2754

Browse files
committed
Schedule work to update Context.Consumer inside Suspense
1 parent fb36d98 commit aea2754

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ import type {SharedQueue} from './ReactUpdateQueue.new';
2020
import {isPrimaryRenderer} from './ReactFiberHostConfig';
2121
import {createCursor, push, pop} from './ReactFiberStack.new';
2222
import {
23+
ContextConsumer,
2324
ContextProvider,
2425
ClassComponent,
2526
DehydratedFragment,
27+
OffscreenComponent,
28+
SuspenseComponent,
2629
} from './ReactWorkTags';
2730
import {
2831
NoLanes,
@@ -157,6 +160,10 @@ export function scheduleWorkOnParentPath(
157160
!isSubsetOfLanes(alternate.childLanes, renderLanes)
158161
) {
159162
alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
163+
} else {
164+
// Neither alternate was updated, which means the rest of the
165+
// ancestor path already has sufficient priority.
166+
break;
160167
}
161168
node = node.return;
162169
}
@@ -361,6 +368,66 @@ function propagateContextChanges<T>(
361368
}
362369
scheduleWorkOnParentPath(consumer.return, renderLanes);
363370

371+
// If Context.Consumer is a descendant of Suspense,
372+
// `scheduleWorkOnParentPath` may break before it get to Suspense.
373+
// Schedule work to avoid bailout before Context.Consumer receives the value.
374+
const contextConsumerIsDescendantOfSuspense =
375+
workInProgress.tag === SuspenseComponent &&
376+
workInProgress.child.tag === OffscreenComponent &&
377+
consumer.tag === ContextConsumer;
378+
if (contextConsumerIsDescendantOfSuspense) {
379+
console.log(' contextConsumerWrappedBySuspense');
380+
if (!isSubsetOfLanes(workInProgress.childLanes, renderLanes)) {
381+
workInProgress.childLanes = mergeLanes(
382+
workInProgress.childLanes,
383+
renderLanes,
384+
);
385+
if (workInProgress.alternate !== null) {
386+
workInProgress.alternate.childLanes = mergeLanes(
387+
workInProgress.alternate.childLanes,
388+
renderLanes,
389+
);
390+
}
391+
} else if (
392+
workInProgress.alternate !== null &&
393+
!isSubsetOfLanes(
394+
workInProgress.alternate.childLanes,
395+
renderLanes,
396+
)
397+
) {
398+
workInProgress.alternate.childLanes = mergeLanes(
399+
workInProgress.alternate.childLanes,
400+
renderLanes,
401+
);
402+
}
403+
const primaryChildFragment = workInProgress.child;
404+
if (
405+
!isSubsetOfLanes(primaryChildFragment.childLanes, renderLanes)
406+
) {
407+
primaryChildFragment.childLanes = mergeLanes(
408+
primaryChildFragment.childLanes,
409+
renderLanes,
410+
);
411+
if (primaryChildFragment.alternate !== null) {
412+
primaryChildFragment.alternate.childLanes = mergeLanes(
413+
primaryChildFragment.alternate.childLanes,
414+
renderLanes,
415+
);
416+
}
417+
} else if (
418+
primaryChildFragment.alternate !== null &&
419+
!isSubsetOfLanes(
420+
primaryChildFragment.alternate.childLanes,
421+
renderLanes,
422+
)
423+
) {
424+
primaryChildFragment.alternate.childLanes = mergeLanes(
425+
primaryChildFragment.alternate.childLanes,
426+
renderLanes,
427+
);
428+
}
429+
}
430+
364431
if (!forcePropagateEntireTree) {
365432
// During lazy propagation, when we find a match, we can defer
366433
// propagating changes to the children, because we're going to

packages/react-reconciler/src/ReactFiberNewContext.old.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ export function scheduleWorkOnParentPath(
157157
!isSubsetOfLanes(alternate.childLanes, renderLanes)
158158
) {
159159
alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
160+
} else {
161+
// Neither alternate was updated, which means the rest of the
162+
// ancestor path already has sufficient priority.
163+
break;
160164
}
161165
node = node.return;
162166
}

0 commit comments

Comments
 (0)