Skip to content

Commit 4001382

Browse files
committed
Dedupe suspense boundaries when it has already been found earlier
1 parent 56b1447 commit 4001382

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

packages/react-dom/src/__tests__/ReactDOMFizzStaticBrowser-test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,4 +840,51 @@ describe('ReactDOMFizzStaticBrowser', () => {
840840
</div>,
841841
]);
842842
});
843+
844+
// @gate enablePostpone
845+
it('can postpone a boundary after it has already been added', async () => {
846+
let prerendering = true;
847+
function Postpone() {
848+
if (prerendering) {
849+
React.unstable_postpone();
850+
}
851+
return 'Hello';
852+
}
853+
854+
function App() {
855+
return (
856+
<div>
857+
<Suspense fallback="Loading...">
858+
<Suspense fallback="Loading...">
859+
<Postpone />
860+
</Suspense>
861+
<Postpone />
862+
<Postpone />
863+
</Suspense>
864+
</div>
865+
);
866+
}
867+
868+
const prerendered = await ReactDOMFizzStatic.prerender(<App />);
869+
expect(prerendered.postponed).not.toBe(null);
870+
871+
prerendering = false;
872+
873+
console.log(JSON.stringify(prerendered.postponed, null, 2));
874+
875+
const resumed = await ReactDOMFizzServer.resume(
876+
<App />,
877+
JSON.parse(JSON.stringify(prerendered.postponed)),
878+
);
879+
880+
await readIntoContainer(prerendered.prelude);
881+
882+
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
883+
884+
await readIntoContainer(resumed);
885+
886+
expect(getVisibleChildren(container)).toEqual(
887+
<div>{['Hello', 'Hello', 'Hello']}</div>,
888+
);
889+
});
843890
});

packages/react-server/src/ReactFizzServer.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,15 +2490,23 @@ function trackPostpone(
24902490
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
24912491
return;
24922492
} else {
2493-
const boundaryNode: ReplaySuspenseBoundary = [
2494-
boundaryKeyPath[1],
2495-
boundaryKeyPath[2],
2496-
children,
2497-
null,
2498-
boundary.rootSegmentID,
2499-
];
2500-
trackedPostpones.workingMap.set(boundaryKeyPath, boundaryNode);
2501-
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
2493+
let boundaryNode: void | ReplayNode =
2494+
trackedPostpones.workingMap.get(boundaryKeyPath);
2495+
if (boundaryNode === undefined) {
2496+
boundaryNode = [
2497+
boundaryKeyPath[1],
2498+
boundaryKeyPath[2],
2499+
children,
2500+
null,
2501+
boundary.rootSegmentID,
2502+
];
2503+
trackedPostpones.workingMap.set(boundaryKeyPath, boundaryNode);
2504+
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
2505+
} else {
2506+
// Upgrade to ReplaySuspenseBoundary.
2507+
((boundaryNode: any): ReplaySuspenseBoundary)[4] =
2508+
boundary.rootSegmentID;
2509+
}
25022510
// Fall through to add the child node.
25032511
}
25042512
}

0 commit comments

Comments
 (0)