mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
[DevTools] Fix instrumentation error when reconciling promise-as-a-child (#34587)
This commit is contained in:
parent
8ad773b1f3
commit
c44fbf43b1
|
|
@ -3107,4 +3107,45 @@ describe('Store', () => {
|
||||||
await actAsync(() => render(<span />));
|
await actAsync(() => render(<span />));
|
||||||
expect(store).toMatchInlineSnapshot(`[root]`);
|
expect(store).toMatchInlineSnapshot(`[root]`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @reactVersion >= 19.0
|
||||||
|
it('should reconcile promise-as-a-child', async () => {
|
||||||
|
function Component({children}) {
|
||||||
|
return <div>{children}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
await actAsync(() =>
|
||||||
|
render(
|
||||||
|
<React.Suspense>
|
||||||
|
{Promise.resolve(<Component key="A">A</Component>)}
|
||||||
|
</React.Suspense>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(store).toMatchInlineSnapshot(`
|
||||||
|
[root]
|
||||||
|
▾ <Suspense>
|
||||||
|
<Component key="A">
|
||||||
|
[suspense-root] rects={[{x:1,y:2,width:1,height:1}]}
|
||||||
|
<Suspense name="Unknown" rects={[{x:1,y:2,width:1,height:1}]}>
|
||||||
|
`);
|
||||||
|
|
||||||
|
await actAsync(() =>
|
||||||
|
render(
|
||||||
|
<React.Suspense>
|
||||||
|
{Promise.resolve(<Component key="not-A">not A</Component>)}
|
||||||
|
</React.Suspense>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(store).toMatchInlineSnapshot(`
|
||||||
|
[root]
|
||||||
|
▾ <Suspense>
|
||||||
|
<Component key="not-A">
|
||||||
|
[suspense-root] rects={[{x:1,y:2,width:5,height:1}]}
|
||||||
|
<Suspense name="Unknown" rects={[{x:1,y:2,width:5,height:1}]}>
|
||||||
|
`);
|
||||||
|
|
||||||
|
await actAsync(() => render(null));
|
||||||
|
expect(store).toMatchInlineSnapshot(``);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2886,9 +2886,16 @@ export function attach(
|
||||||
previousSuspendedBy: null | Array<ReactAsyncInfo>,
|
previousSuspendedBy: null | Array<ReactAsyncInfo>,
|
||||||
parentSuspenseNode: null | SuspenseNode,
|
parentSuspenseNode: null | SuspenseNode,
|
||||||
): void {
|
): void {
|
||||||
// Remove any async info from the parent, if they were in the previous set but
|
// Remove any async info if they were in the previous set but
|
||||||
// is no longer in the new set.
|
// is no longer in the new set.
|
||||||
if (previousSuspendedBy !== null && parentSuspenseNode !== null) {
|
// If we just reconciled a SuspenseNode, we need to remove from that node instead of the parent.
|
||||||
|
// This is different from inserting because inserting is done during reconiliation
|
||||||
|
// whereas removal is done after we're done reconciling.
|
||||||
|
const suspenseNode =
|
||||||
|
instance.suspenseNode === null
|
||||||
|
? parentSuspenseNode
|
||||||
|
: instance.suspenseNode;
|
||||||
|
if (previousSuspendedBy !== null && suspenseNode !== null) {
|
||||||
const nextSuspendedBy = instance.suspendedBy;
|
const nextSuspendedBy = instance.suspendedBy;
|
||||||
for (let i = 0; i < previousSuspendedBy.length; i++) {
|
for (let i = 0; i < previousSuspendedBy.length; i++) {
|
||||||
const asyncInfo = previousSuspendedBy[i];
|
const asyncInfo = previousSuspendedBy[i];
|
||||||
|
|
@ -2901,7 +2908,7 @@ export function attach(
|
||||||
// This IO entry is no longer blocking the current tree.
|
// This IO entry is no longer blocking the current tree.
|
||||||
// Let's remove it from the parent SuspenseNode.
|
// Let's remove it from the parent SuspenseNode.
|
||||||
const ioInfo = asyncInfo.awaited;
|
const ioInfo = asyncInfo.awaited;
|
||||||
const suspendedBySet = parentSuspenseNode.suspendedBy.get(ioInfo);
|
const suspendedBySet = suspenseNode.suspendedBy.get(ioInfo);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
suspendedBySet === undefined ||
|
suspendedBySet === undefined ||
|
||||||
|
|
@ -2928,16 +2935,16 @@ export function attach(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (suspendedBySet !== undefined && suspendedBySet.size === 0) {
|
if (suspendedBySet !== undefined && suspendedBySet.size === 0) {
|
||||||
parentSuspenseNode.suspendedBy.delete(asyncInfo.awaited);
|
suspenseNode.suspendedBy.delete(asyncInfo.awaited);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
parentSuspenseNode.hasUniqueSuspenders &&
|
suspenseNode.hasUniqueSuspenders &&
|
||||||
!ioExistsInSuspenseAncestor(parentSuspenseNode, ioInfo)
|
!ioExistsInSuspenseAncestor(suspenseNode, ioInfo)
|
||||||
) {
|
) {
|
||||||
// This entry wasn't in any ancestor and is no longer in this suspense boundary.
|
// This entry wasn't in any ancestor and is no longer in this suspense boundary.
|
||||||
// This means that a child might now be the unique suspender for this IO.
|
// This means that a child might now be the unique suspender for this IO.
|
||||||
// Search the child boundaries to see if we can reveal any of them.
|
// Search the child boundaries to see if we can reveal any of them.
|
||||||
unblockSuspendedBy(parentSuspenseNode, ioInfo);
|
unblockSuspendedBy(suspenseNode, ioInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user