Skip to content

Commit ef35e50

Browse files
committed
Move onCompleteAll to .allReady Promise
The onCompleteAll callback can sometimes resolve before the promise that returns the stream which is tough to coordinate. A more idiomatic API for a one shot event is a Promise. That way the way you render for SEO or SSG is: const stream = await renderToReadableStream(...); await stream.readyAll; respondWith(stream); Ideally this should be a sub-class of ReadableStream but we don't yet compile these to ES6 and they'd had to be to native class to subclass a native stream. I have other ideas for overriding the .tee() method in a subclass anyway. So this is inline with that strategy.
1 parent 05c283c commit ef35e50

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,10 @@ describe('ReactDOMFizzServer', () => {
105105
<Wait />
106106
</Suspense>
107107
</div>,
108-
{
109-
onCompleteAll() {
110-
isComplete = true;
111-
},
112-
},
113108
);
109+
110+
stream.allReady.then(() => (isComplete = true));
111+
114112
await jest.runAllTimers();
115113
expect(isComplete).toBe(false);
116114
// Resolve the loading.

packages/react-dom/src/server/ReactDOMFizzServerBrowser.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,34 @@ type Options = {|
3232
bootstrapModules?: Array<string>,
3333
progressiveChunkSize?: number,
3434
signal?: AbortSignal,
35-
onCompleteAll?: () => void,
3635
onError?: (error: mixed) => void,
3736
|};
3837

38+
// TODO: Move to sub-classing ReadableStream.
39+
type ReactDOMServerReadableStream = ReadableStream & {
40+
allReady: Promise<void>,
41+
};
42+
3943
function renderToReadableStream(
4044
children: ReactNodeList,
4145
options?: Options,
42-
): Promise<ReadableStream> {
46+
): Promise<ReactDOMServerReadableStream> {
4347
return new Promise((resolve, reject) => {
48+
let onCompleteAll;
49+
const allReady = new Promise(res => {
50+
onCompleteAll = res;
51+
});
52+
4453
function onCompleteShell() {
45-
const stream = new ReadableStream({
54+
const stream: ReactDOMServerReadableStream = (new ReadableStream({
4655
type: 'bytes',
4756
pull(controller) {
4857
startFlowing(request, controller);
4958
},
5059
cancel(reason) {},
51-
});
60+
}): any);
61+
// TODO: Move to sub-classing ReadableStream.
62+
stream.allReady = allReady;
5263
resolve(stream);
5364
}
5465
function onErrorShell(error: mixed) {
@@ -66,7 +77,7 @@ function renderToReadableStream(
6677
createRootFormatContext(options ? options.namespaceURI : undefined),
6778
options ? options.progressiveChunkSize : undefined,
6879
options ? options.onError : undefined,
69-
options ? options.onCompleteAll : undefined,
80+
onCompleteAll,
7081
onCompleteShell,
7182
onErrorShell,
7283
);

0 commit comments

Comments
 (0)