@@ -1085,87 +1085,108 @@ function finishConcurrentRender(
10851085 finishedWork : Fiber ,
10861086 lanes : Lanes ,
10871087) {
1088- // TODO: The fact that most of these branches are identical suggests that some
1089- // of the exit statuses are not best modeled as exit statuses and should be
1090- // tracked orthogonally.
10911088 switch ( exitStatus ) {
10921089 case RootInProgress :
10931090 case RootFatalErrored : {
10941091 throw new Error ( 'Root did not complete. This is a bug in React.' ) ;
10951092 }
1093+ case RootErrored : {
1094+ // We should have already attempted to retry this tree. If we reached
1095+ // this point, it errored again. Commit it.
1096+ commitRootWhenReady (
1097+ root ,
1098+ finishedWork ,
1099+ workInProgressRootRecoverableErrors ,
1100+ workInProgressTransitions ,
1101+ lanes ,
1102+ ) ;
1103+ break ;
1104+ }
1105+ case RootSuspended : {
1106+ markRootSuspended ( root , lanes ) ;
1107+
1108+ // We have an acceptable loading state. We need to figure out if we
1109+ // should immediately commit it or wait a bit.
1110+
1111+ if (
1112+ includesOnlyRetries ( lanes ) &&
1113+ // do not delay if we're inside an act() scope
1114+ ! shouldForceFlushFallbacksInDEV ( )
1115+ ) {
1116+ // This render only included retries, no updates. Throttle committing
1117+ // retries so that we don't show too many loading states too quickly.
1118+ const msUntilTimeout =
1119+ globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now ( ) ;
1120+ // Don't bother with a very short suspense time.
1121+ if ( msUntilTimeout > 10 ) {
1122+ const nextLanes = getNextLanes ( root , NoLanes ) ;
1123+ if ( nextLanes !== NoLanes ) {
1124+ // There's additional work on this root.
1125+ break ;
1126+ }
1127+
1128+ // The render is suspended, it hasn't timed out, and there's no
1129+ // lower priority work to do. Instead of committing the fallback
1130+ // immediately, wait for more data to arrive.
1131+ root . timeoutHandle = scheduleTimeout (
1132+ commitRootWhenReady . bind (
1133+ null ,
1134+ root ,
1135+ finishedWork ,
1136+ workInProgressRootRecoverableErrors ,
1137+ workInProgressTransitions ,
1138+ lanes ,
1139+ ) ,
1140+ msUntilTimeout ,
1141+ ) ;
1142+ break ;
1143+ }
1144+ }
1145+ // The work expired. Commit immediately.
1146+ commitRootWhenReady (
1147+ root ,
1148+ finishedWork ,
1149+ workInProgressRootRecoverableErrors ,
1150+ workInProgressTransitions ,
1151+ lanes ,
1152+ ) ;
1153+ break ;
1154+ }
10961155 case RootSuspendedWithDelay : {
1156+ markRootSuspended ( root , lanes ) ;
1157+
10971158 if ( includesOnlyTransitions ( lanes ) ) {
10981159 // This is a transition, so we should exit without committing a
10991160 // placeholder and without scheduling a timeout. Delay indefinitely
11001161 // until we receive more data.
1101- markRootSuspended ( root , lanes ) ;
1102- return ;
1162+ break ;
11031163 }
1164+
11041165 // Commit the placeholder.
1166+ commitRootWhenReady (
1167+ root ,
1168+ finishedWork ,
1169+ workInProgressRootRecoverableErrors ,
1170+ workInProgressTransitions ,
1171+ lanes ,
1172+ ) ;
11051173 break ;
11061174 }
1107- case RootErrored :
1108- case RootSuspended :
11091175 case RootCompleted : {
1176+ // The work completed.
1177+ commitRootWhenReady (
1178+ root ,
1179+ finishedWork ,
1180+ workInProgressRootRecoverableErrors ,
1181+ workInProgressTransitions ,
1182+ lanes ,
1183+ ) ;
11101184 break ;
11111185 }
11121186 default : {
11131187 throw new Error ( 'Unknown root exit status.' ) ;
11141188 }
11151189 }
1116-
1117- if ( shouldForceFlushFallbacksInDEV ( ) ) {
1118- // We're inside an `act` scope. Commit immediately.
1119- commitRoot (
1120- root ,
1121- workInProgressRootRecoverableErrors ,
1122- workInProgressTransitions ,
1123- ) ;
1124- } else {
1125- if ( includesOnlyRetries ( lanes ) ) {
1126- // This render only included retries, no updates. Throttle committing
1127- // retries so that we don't show too many loading states too quickly.
1128- const msUntilTimeout =
1129- globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now ( ) ;
1130-
1131- // Don't bother with a very short suspense time.
1132- if ( msUntilTimeout > 10 ) {
1133- markRootSuspended ( root , lanes ) ;
1134-
1135- const nextLanes = getNextLanes ( root , NoLanes ) ;
1136- if ( nextLanes !== NoLanes ) {
1137- // There's additional work we can do on this root. We might as well
1138- // attempt to work on that while we're suspended.
1139- return ;
1140- }
1141-
1142- // The render is suspended, it hasn't timed out, and there's no
1143- // lower priority work to do. Instead of committing the fallback
1144- // immediately, wait for more data to arrive.
1145- // TODO: Combine retry throttling with Suspensey commits. Right now they
1146- // run one after the other.
1147- root . timeoutHandle = scheduleTimeout (
1148- commitRootWhenReady . bind (
1149- null ,
1150- root ,
1151- finishedWork ,
1152- workInProgressRootRecoverableErrors ,
1153- workInProgressTransitions ,
1154- lanes ,
1155- ) ,
1156- msUntilTimeout ,
1157- ) ;
1158- return ;
1159- }
1160- }
1161- commitRootWhenReady (
1162- root ,
1163- finishedWork ,
1164- workInProgressRootRecoverableErrors ,
1165- workInProgressTransitions ,
1166- lanes ,
1167- ) ;
1168- }
11691190}
11701191
11711192function commitRootWhenReady (
@@ -1175,8 +1196,6 @@ function commitRootWhenReady(
11751196 transitions : Array < Transition > | null ,
11761197 lanes : Lanes ,
11771198) {
1178- // TODO: Combine retry throttling with Suspensey commits. Right now they run
1179- // one after the other.
11801199 if ( includesOnlyNonUrgentLanes ( lanes ) ) {
11811200 // Before committing, ask the renderer whether the host tree is ready.
11821201 // If it's not, we'll wait until it notifies us.
@@ -1199,15 +1218,22 @@ function commitRootWhenReady(
11991218 // us that it's ready. This will be canceled if we start work on the
12001219 // root again.
12011220 root . cancelPendingCommit = schedulePendingCommit (
1202- commitRoot . bind ( null , root , recoverableErrors , transitions ) ,
1221+ commitRoot . bind (
1222+ null ,
1223+ root ,
1224+ workInProgressRootRecoverableErrors ,
1225+ workInProgressTransitions ,
1226+ ) ,
12031227 ) ;
1204- markRootSuspended ( root , lanes ) ;
12051228 return ;
12061229 }
12071230 }
1208-
12091231 // Otherwise, commit immediately.
1210- commitRoot ( root , recoverableErrors , transitions ) ;
1232+ commitRoot (
1233+ root ,
1234+ workInProgressRootRecoverableErrors ,
1235+ workInProgressTransitions ,
1236+ ) ;
12111237}
12121238
12131239function isRenderConsistentWithExternalStores ( finishedWork : Fiber ) : boolean {
0 commit comments