Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,84 @@ describe('ReactDOMFizzServer', () => {
</div>,
);
});

// @gate experimental
it('should allow for two containers to be written to the same document', async () => {
// We create two passthrough streams for each container to write into.
// Notably we don't implement a end() call for these. Because we don't want to
// close the underlying stream just because one of the streams is done. Instead
// we manually close when both are done.
const writableA = new Stream.Writable();
writableA._write = (chunk, encoding, next) => {
writable.write(chunk, encoding, next);
};
const writableB = new Stream.Writable();
writableB._write = (chunk, encoding, next) => {
writable.write(chunk, encoding, next);
};

writable.write('<div id="container-A">');
await act(async () => {
const {startWriting} = ReactDOMFizzServer.pipeToNodeWritable(
<Suspense fallback={<Text text="Loading A..." />}>
<Text text="This will show A: " />
<div>
<AsyncText text="A" />
</div>
</Suspense>,
writableA,
{identifierPrefix: 'A_'},
);
startWriting();
});
writable.write('</div>');
Copy link
Collaborator Author

@sebmarkbage sebmarkbage Mar 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is a little difficult to do correctly in practice because there's no explicit signal when a root is flushed. I think the way you'd do that is explicitly wait to start writing until the root is signaled as ready, and then startWriting and assume that it's done writing after a setImmediate tick or something but that's a little flawed. What you probably want is a way to explicitly write the whole root synchronously after it is done loading.

The main pattern we want to support is the legacy synchronous render. This test shows that we can support it for streaming multiple containers though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently startWriting will synchronously emit the root if it's available. We can probably preserve that property.


writable.write('<div id="container-B">');
await act(async () => {
const {startWriting} = ReactDOMFizzServer.pipeToNodeWritable(
<Suspense fallback={<Text text="Loading B..." />}>
<Text text="This will show B: " />
<div>
<AsyncText text="B" />
</div>
</Suspense>,
writableB,
{identifierPrefix: 'B_'},
);
startWriting();
});
writable.write('</div>');

expect(getVisibleChildren(container)).toEqual([
<div id="container-A">Loading A...</div>,
<div id="container-B">Loading B...</div>,
]);

await act(async () => {
resolveText('B');
});

expect(getVisibleChildren(container)).toEqual([
<div id="container-A">Loading A...</div>,
<div id="container-B">
This will show B: <div>B</div>
</div>,
]);

await act(async () => {
resolveText('A');
});

// We're done writing both streams now.
writable.end();

expect(getVisibleChildren(container)).toEqual([
<div id="container-A">
This will show A: <div>A</div>
</div>,
<div id="container-B">
This will show B: <div>B</div>
</div>,
]);
});
});