Skip to content

Commit 06bb3fb

Browse files
committed
[Flight] Deduplicate suspended elements
1 parent fd0da3e commit 06bb3fb

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,4 +2145,74 @@ describe('ReactFlight', () => {
21452145
expect(loggedFn).not.toBe(foo);
21462146
expect(loggedFn.toString()).toBe(foo.toString());
21472147
});
2148+
2149+
// @gate __DEV__
2150+
it('does not emit duplicate chunks for already outlined elements in dev mode', async () => {
2151+
async function Bar({text}) {
2152+
return <div>{text.toUpperCase()}</div>;
2153+
}
2154+
2155+
function Foo() {
2156+
const bar = <Bar text="bar" />;
2157+
2158+
return (
2159+
<div>
2160+
{bar}
2161+
{bar}
2162+
</div>
2163+
);
2164+
}
2165+
2166+
const transport = ReactNoopFlightServer.render(<Foo />);
2167+
const textDecoder = new TextDecoder();
2168+
2169+
await act(async () => {
2170+
const chunks = transport
2171+
.map(chunk => textDecoder.decode(chunk).replace(/\n$/, ''))
2172+
.join('\n');
2173+
2174+
expect(chunks).toEqual(
2175+
`
2176+
0:D{"name":"Foo","env":"Server"}
2177+
1:D{"name":"Bar","env":"Server"}
2178+
0:["$","div",null,{"children":["$L1","$1"]}]
2179+
1:["$","div",null,{"children":"BAR"}]
2180+
`.trim(),
2181+
);
2182+
});
2183+
});
2184+
2185+
// @gate !__DEV__
2186+
it('does not emit duplicate chunks for already outlined elements in production mode', async () => {
2187+
async function Bar({text}) {
2188+
return <div>{text.toUpperCase()}</div>;
2189+
}
2190+
2191+
function Foo() {
2192+
const bar = <Bar text="bar" />;
2193+
2194+
return (
2195+
<div>
2196+
{bar}
2197+
{bar}
2198+
</div>
2199+
);
2200+
}
2201+
2202+
const transport = ReactNoopFlightServer.render(<Foo />);
2203+
const textDecoder = new TextDecoder();
2204+
2205+
await act(async () => {
2206+
const chunks = transport
2207+
.map(chunk => textDecoder.decode(chunk).replace(/\n$/, ''))
2208+
.join('\n');
2209+
2210+
expect(chunks).toEqual(
2211+
`
2212+
0:["$","div",null,{"children":["$L1","$1"]}]
2213+
1:["$","div",null,{"children":"BAR"}]
2214+
`.trim(),
2215+
);
2216+
});
2217+
});
21482218
});

packages/react-server/src/ReactFlightServer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,9 @@ function renderModel(
12371237
task.implicitSlot,
12381238
request.abortableTasks,
12391239
);
1240+
// The suspended element was outlined, so we're using the same ID for the
1241+
// original value, thus ensuring that it's deduplicated if it's referenced again.
1242+
request.writtenObjects.set((value: any), newTask.id);
12401243
const ping = newTask.ping;
12411244
(x: any).then(ping, ping);
12421245
newTask.thenableState = getThenableStateAfterSuspending();

0 commit comments

Comments
 (0)