1023
1024
it(
1025
'continues rendering asynchronously even if a promise is captured by ' +
1026
- 'a sync boundary (strict)',
1026
+ 'a sync boundary (default mode)',
1027
async () => {
1028
class UpdatingText extends React.Component {
1029
state = {text: this.props.initialText};
1036
const text2 = React.createRef(null);
1037
function App() {
1038
return (
1039
- <StrictMode>
1039
+ <Fragment>
1040
<Suspense
1041
maxDuration={1000}
1042
fallback={<Text text="Loading..." />}>
1063
)}
1064
</UpdatingText>
1065
</ConcurrentMode>
1066
- </StrictMode>
1066
+ </Fragment>
1067
);
1068
}
1069
1076
'Before',
1077
'Suspend! [Async: 1]',
1078
'After',
1079
- 'Loading...',
1079
'Before',
1080
'Sync: 1',
1081
'After',
1082
'Did mount',
1083
+ // The placeholder is rendered in a subsequent commit
1084
+ 'Loading...',
1085
'Promise resolved [Async: 1]',
1085
- 'Before',
1086
'Async: 1',
1087
- 'After',
1088
- ]);
1089
- expect(ReactNoop.getChildren()).toEqual([
1090
- span('Before'),
1091
- span('Async: 1'),
1092
- span('After'),
1093
-
1094
- span('Before'),
1095
- span('Sync: 1'),
1096
- span('After'),
1087
]);
1088
+ expect(ReactNoop.getChildrenAsJSX()).toEqual(
1089
+ <React.Fragment>
1090
+ <span prop="Before" />
1091
+ <span prop="Async: 1" />
1092
+ <span prop="After" />
1093
+
1094
+ <span prop="Before" />
1095
+ <span prop="Sync: 1" />
1096
+ <span prop="After" />
1097
+ </React.Fragment>,
1098
+ );
1099
1100
// Update. This starts out asynchronously.
1101
text1.current.setState({text: 'Async: 2'}, () =>
1106
);
1107
1108
// Start rendering asynchronously
1108
- ReactNoop.flushThrough([
1109
- 'Before',
1109
+ ReactNoop.flushThrough(['Before']);
1110
+
1111
+ // Now render the next child, which suspends
1112
+ expect(ReactNoop.flushNextYield()).toEqual([
1113
// This child suspends
1114
'Suspend! [Async: 2]',
1112
- // But we can still render the rest of the async tree asynchronously
1113
- 'After',
1115
]);
1115
-
1116
- // Suspend during an async render.
1117
- expect(ReactNoop.flushNextYield()).toEqual(['Loading...']);
1118
- expect(ReactNoop.flush()).toEqual(['Before', 'Sync: 2', 'After']);
1119
- // Commit was suspended.
1120
- expect(ReactNoop.getChildren()).toEqual([
1121
- span('Before'),
1122
- span('Async: 1'),
1123
- span('After'),
1124
-
1125
- span('Before'),
1126
- span('Sync: 1'),
1127
- span('After'),
1128
- ]);
1129
-
1130
- // When the placeholder is pinged, the boundary re-
1131
- // renders asynchronously.
1132
- ReactNoop.expire(100);
1133
- await advanceTimers(100);
1116
expect(ReactNoop.flush()).toEqual([
1135
- 'Promise resolved [Async: 2]',
1136
- 'Before',
1137
- 'Async: 2',
1117
'After',
1118
'Before',
1119
'Sync: 2',
1120
'After',
1121
'Update 1 did commit',
1122
'Update 2 did commit',
1123
+
1124
+ // Switch to the placeholder in a subsequent commit
1125
+ 'Loading...',
1126
]);
1127
+ expect(ReactNoop.getChildrenAsJSX()).toEqual(
1128
+ <React.Fragment>
1129
+ <span hidden={true} prop="Before" />
1130
+ <span hidden={true} prop="After" />
1131
+ <span prop="Loading..." />
1132
1146
- expect(ReactNoop.getChildren()).toEqual([
1147
- span('Before'),
1148
- span('Async: 2'),
1149
- span('After'),
1133
+ <span prop="Before" />
1134
+ <span prop="Sync: 2" />
1135
+ <span prop="After" />
1136
+ </React.Fragment>,
1137
+ );
1138
1151
- span('Before'),
1152
- span('Sync: 2'),
1153
- span('After'),
1139
+ // When the placeholder is pinged, the boundary must be re-rendered
1140
+ // synchronously.
1141
+ await advanceTimers(100);
1142
+ expect(ReactNoop.clearYields()).toEqual([
1143
+ 'Promise resolved [Async: 2]',
1144
+ 'Async: 2',
1145
]);
1146
+
1147
+ expect(ReactNoop.getChildrenAsJSX()).toEqual(
1148
+ <React.Fragment>
1149
+ <span prop="Before" />
1150
+ <span prop="Async: 2" />
1151
+ <span prop="After" />
1152
+
1153
+ <span prop="Before" />
1154
+ <span prop="Sync: 2" />
1155
+ <span prop="After" />
1156
+ </React.Fragment>,
1157
+ );
1158
},
1159
);
1160
1161
it(
1162
'continues rendering asynchronously even if a promise is captured by ' +
1160
- 'a sync boundary (loose)',
1163
+ 'a sync boundary (strict, non-concurrent)',
1164
async () => {
1165
class UpdatingText extends React.Component {
1166
state = {text: this.props.initialText};
1173
const text2 = React.createRef(null);
1174
function App() {
1175
return (
1173
- <Fragment>
1176
+ <StrictMode>
1177
<Suspense
1178
maxDuration={1000}
1179
fallback={<Text text="Loading..." />}>
1200
)}
1201
</UpdatingText>
1202
</ConcurrentMode>
1200
- </Fragment>
1203
+ </StrictMode>
1204
);
1205
}
1206