Skip to content

Commit ffecb30

Browse files
committed
Emit reactroot attribute on the first element we discover
This may not be the first root element if the root is a fragment and the second one unsuspends first. But this tag doesn't work well for root fragments anyway.
1 parent dbc8fb9 commit ffecb30

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

packages/react-dom/src/server/ReactDOMServerFormatConfig.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
OVERLOADED_BOOLEAN,
3333
NUMERIC,
3434
POSITIVE_NUMERIC,
35+
ROOT_ATTRIBUTE_NAME,
3536
} from '../shared/DOMProperty';
3637
import {isUnitlessNumber} from '../shared/CSSProperty';
3738

@@ -59,6 +60,7 @@ export type ResponseState = {
5960
sentCompleteSegmentFunction: boolean,
6061
sentCompleteBoundaryFunction: boolean,
6162
sentClientRenderFunction: boolean,
63+
hasEmittedRoot: boolean,
6264
};
6365

6466
// Allows us to keep track of what we've already written so we can refer back to it.
@@ -74,6 +76,7 @@ export function createResponseState(
7476
sentCompleteSegmentFunction: false,
7577
sentCompleteBoundaryFunction: false,
7678
sentClientRenderFunction: false,
79+
hasEmittedRoot: false,
7780
};
7881
}
7982

@@ -94,7 +97,7 @@ type InsertionMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
9497

9598
// Lets us keep track of contextual state and pick it back up after suspending.
9699
export type FormatContext = {
97-
insertionMode: InsertionMode, // root/svg/html/mathml/table
100+
insertionMode: InsertionMode, // svg/html/mathml/table
98101
selectedValue: null | string | Array<string>, // the selected value(s) inside a <select>, or null outside <select>
99102
};
100103

@@ -487,6 +490,13 @@ const endOfStartTagSelfClosing = stringToPrecomputedChunk('/>');
487490
const idAttr = stringToPrecomputedChunk(' id="');
488491
const attrEnd = stringToPrecomputedChunk('"');
489492

493+
const reactRootAttribute = stringToPrecomputedChunk(' ' + ROOT_ATTRIBUTE_NAME + '=""');
494+
function pushReactRoot(target: Array<Chunk | PrecomputedChunk>, responseState: ResponseState): void {
495+
if (!responseState.hasEmittedRoot) {
496+
target.push(reactRootAttribute);
497+
}
498+
}
499+
490500
function pushID(
491501
target: Array<Chunk | PrecomputedChunk>,
492502
responseState: ResponseState,
@@ -618,6 +628,7 @@ function pushStartSelect(
618628
if (assignID !== null) {
619629
pushID(target, responseState, assignID, props.id);
620630
}
631+
pushReactRoot(target, responseState);
621632

622633
target.push(endOfStartTag);
623634
pushInnerHTML(target, innerHTML, children);
@@ -731,6 +742,7 @@ function pushStartOption(
731742
if (assignID !== null) {
732743
pushID(target, responseState, assignID, props.id);
733744
}
745+
pushReactRoot(target, responseState);
734746

735747
target.push(endOfStartTag);
736748
return children;
@@ -818,6 +830,7 @@ function pushInput(
818830
if (assignID !== null) {
819831
pushID(target, responseState, assignID, props.id);
820832
}
833+
pushReactRoot(target, responseState);
821834

822835
target.push(endOfStartTagSelfClosing);
823836
return null;
@@ -882,6 +895,7 @@ function pushStartTextArea(
882895
if (assignID !== null) {
883896
pushID(target, responseState, assignID, props.id);
884897
}
898+
pushReactRoot(target, responseState);
885899

886900
target.push(endOfStartTag);
887901

@@ -958,6 +972,7 @@ function pushSelfClosing(
958972
if (assignID !== null) {
959973
pushID(target, responseState, assignID, props.id);
960974
}
975+
pushReactRoot(target, responseState);
961976

962977
target.push(endOfStartTagSelfClosing);
963978
return null;
@@ -994,6 +1009,7 @@ function pushStartMenuItem(
9941009
if (assignID !== null) {
9951010
pushID(target, responseState, assignID, props.id);
9961011
}
1012+
pushReactRoot(target, responseState);
9971013

9981014
target.push(endOfStartTag);
9991015
return null;
@@ -1032,6 +1048,7 @@ function pushStartGenericElement(
10321048
if (assignID !== null) {
10331049
pushID(target, responseState, assignID, props.id);
10341050
}
1051+
pushReactRoot(target, responseState);
10351052

10361053
target.push(endOfStartTag);
10371054
pushInnerHTML(target, innerHTML, children);
@@ -1086,6 +1103,7 @@ function pushStartCustomElement(
10861103
if (assignID !== null) {
10871104
pushID(target, responseState, assignID, props.id);
10881105
}
1106+
pushReactRoot(target, responseState);
10891107

10901108
target.push(endOfStartTag);
10911109
pushInnerHTML(target, innerHTML, children);
@@ -1127,6 +1145,7 @@ function pushStartPreformattedElement(
11271145
if (assignID !== null) {
11281146
pushID(target, responseState, assignID, props.id);
11291147
}
1148+
pushReactRoot(target, responseState);
11301149

11311150
target.push(endOfStartTag);
11321151

0 commit comments

Comments
 (0)