Assign resolved outlined props to element object (and not only tuple) (#30528)

Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
This commit is contained in:
Hendrik Liebau
2024-07-30 21:31:32 +02:00
committed by GitHub
co-authored by eps1lon
parent f827c792ea
commit 3208e73e82
2 changed files with 112 additions and 0 deletions
+14
View File
@@ -902,6 +902,20 @@ function waitForReference<T>(
handler.value = parentObject[key];
}
// If the parent object is an unparsed React element tuple and its outlined
// props have now been resolved, we also need to update the props of the
// parsed element object (i.e. handler.value).
if (
parentObject[0] === REACT_ELEMENT_TYPE &&
key === '3' &&
typeof handler.value === 'object' &&
handler.value !== null &&
handler.value.$$typeof === REACT_ELEMENT_TYPE &&
handler.value.props === null
) {
handler.value.props = parentObject[key];
}
handler.deps--;
if (handler.deps === 0) {
@@ -525,6 +525,104 @@ describe('ReactFlightDOMBrowser', () => {
expect(container.innerHTML).toBe('{"foo":1}{"foo":1}');
});
it('should handle deduped props of re-used elements in fragments (same-chunk reference)', async () => {
let resolveFooClientComponentChunk;
const FooClient = clientExports(
function Foo({children, item}) {
return children;
},
'1',
'/foo.js',
new Promise(resolve => (resolveFooClientComponentChunk = resolve)),
);
const shared = <div />;
function Server() {
return (
<FooClient track={shared}>
<>{shared}</>
</FooClient>
);
}
const stream = await serverAct(() =>
ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),
);
function ClientRoot({response}) {
return use(response);
}
const response = ReactServerDOMClient.createFromReadableStream(stream);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ClientRoot response={response} />);
});
expect(container.innerHTML).toBe('');
await act(() => {
resolveFooClientComponentChunk();
});
expect(container.innerHTML).toBe('<div></div>');
});
it('should handle deduped props of re-used elements in server components (cross-chunk reference)', async () => {
let resolveFooClientComponentChunk;
function PassthroughServerComponent({children}) {
return children;
}
const FooClient = clientExports(
function Foo({children, item}) {
return children;
},
'1',
'/foo.js',
new Promise(resolve => (resolveFooClientComponentChunk = resolve)),
);
const shared = <div />;
function Server() {
return (
<FooClient track={shared}>
<PassthroughServerComponent>{shared}</PassthroughServerComponent>
</FooClient>
);
}
const stream = await serverAct(() =>
ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),
);
function ClientRoot({response}) {
return use(response);
}
const response = ReactServerDOMClient.createFromReadableStream(stream);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ClientRoot response={response} />);
});
expect(container.innerHTML).toBe('');
await act(() => {
resolveFooClientComponentChunk();
});
expect(container.innerHTML).toBe('<div></div>');
});
it('should progressively reveal server components', async () => {
let reportedErrors = [];