diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index b4b8c406424b1..fbebe2bdcdfd2 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -827,7 +827,7 @@ function getChunk(response: Response, id: number): SomeChunk { } function waitForReference( - referencedChunk: PendingChunk | BlockedChunk, + referencedChunk: SomeChunk, parentObject: Object, key: string, response: Response, @@ -1003,6 +1003,21 @@ function getOutlinedModel( let value = chunk.value; for (let i = 1; i < path.length; i++) { value = value[path[i]]; + if (value.$$typeof === REACT_LAZY_TYPE) { + const referencedChunk: SomeChunk = value._payload; + if (referencedChunk.status === INITIALIZED) { + value = referencedChunk.value; + } else { + return waitForReference( + referencedChunk, + parentObject, + key, + response, + map, + path.slice(i), + ); + } + } } const chunkValue = map(response, value); if (__DEV__ && chunk._debugInfo) { diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js index 49f2823c8b387..def347e83a18b 100644 --- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js +++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js @@ -456,6 +456,75 @@ describe('ReactFlightDOMBrowser', () => { expect(container.innerHTML).toBe('{}'); }); + it('should resolve deduped objects in blocked models referencing other blocked models with blocked references', async () => { + let resolveFooClientComponentChunk; + let resolveBarClientComponentChunk; + + function PassthroughServerComponent({children}) { + return children; + } + + const FooClient = clientExports( + function FooClient({children}) { + return JSON.stringify(children); + }, + '1', + '/foo.js', + new Promise(resolve => (resolveFooClientComponentChunk = resolve)), + ); + + const BarClient = clientExports( + function BarClient() { + return 'not used'; + }, + '2', + '/bar.js', + new Promise(resolve => (resolveBarClientComponentChunk = resolve)), + ); + + const shared = {foo: 1}; + + function Server() { + return ( + <> + + + {shared} + + + + {shared} + + + ); + } + + const stream = await serverAct(() => + ReactServerDOMServer.renderToReadableStream(, 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(); + }); + + expect(container.innerHTML).toBe(''); + + await act(() => { + resolveFooClientComponentChunk(); + resolveBarClientComponentChunk(); + }); + + expect(container.innerHTML).toBe('{"foo":1}{"foo":1}'); + }); + it('should progressively reveal server components', async () => { let reportedErrors = [];