diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js
index 55956ddc93ecd..7d0ee2fea5009 100644
--- a/packages/react-client/src/__tests__/ReactFlight-test.js
+++ b/packages/react-client/src/__tests__/ReactFlight-test.js
@@ -2145,4 +2145,74 @@ describe('ReactFlight', () => {
expect(loggedFn).not.toBe(foo);
expect(loggedFn.toString()).toBe(foo.toString());
});
+
+ // @gate __DEV__
+ it('does not emit duplicate chunks for already outlined elements in dev mode', async () => {
+ async function Bar({text}) {
+ return
{text.toUpperCase()}
;
+ }
+
+ function Foo() {
+ const bar = ;
+
+ return (
+
+ {bar}
+ {bar}
+
+ );
+ }
+
+ const transport = ReactNoopFlightServer.render();
+ const textDecoder = new TextDecoder();
+
+ await act(async () => {
+ const chunks = transport
+ .map(chunk => textDecoder.decode(chunk).replace(/\n$/, ''))
+ .join('\n');
+
+ expect(chunks).toEqual(
+ `
+0:D{"name":"Foo","env":"Server"}
+1:D{"name":"Bar","env":"Server"}
+0:["$","div",null,{"children":["$L1","$1"]}]
+1:["$","div",null,{"children":"BAR"}]
+ `.trim(),
+ );
+ });
+ });
+
+ // @gate !__DEV__
+ it('does not emit duplicate chunks for already outlined elements in production mode', async () => {
+ async function Bar({text}) {
+ return {text.toUpperCase()}
;
+ }
+
+ function Foo() {
+ const bar = ;
+
+ return (
+
+ {bar}
+ {bar}
+
+ );
+ }
+
+ const transport = ReactNoopFlightServer.render();
+ const textDecoder = new TextDecoder();
+
+ await act(async () => {
+ const chunks = transport
+ .map(chunk => textDecoder.decode(chunk).replace(/\n$/, ''))
+ .join('\n');
+
+ expect(chunks).toEqual(
+ `
+0:["$","div",null,{"children":["$L1","$1"]}]
+1:["$","div",null,{"children":"BAR"}]
+`.trim(),
+ );
+ });
+ });
});
diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js
index ad0a28f37175c..f4e3f1ef91342 100644
--- a/packages/react-server/src/ReactFlightServer.js
+++ b/packages/react-server/src/ReactFlightServer.js
@@ -1237,6 +1237,9 @@ function renderModel(
task.implicitSlot,
request.abortableTasks,
);
+ // The suspended element was outlined, so we're using the same ID for the
+ // original value, thus ensuring that it's deduplicated if it's referenced again.
+ request.writtenObjects.set((value: any), newTask.id);
const ping = newTask.ping;
(x: any).then(ping, ping);
newTask.thenableState = getThenableStateAfterSuspending();