@@ -1018,20 +1018,16 @@ function updateSuspenseComponent(
1018
1018
// We should attempt to render the primary children unless this boundary
1019
1019
// already suspended during this render (`alreadyCaptured` is true).
1020
1020
let nextState : SuspenseState | null = workInProgress . memoizedState ;
1021
- let nextDidTimeout ;
1022
1021
if ( nextState === null ) {
1023
1022
// An empty suspense state means this boundary has not yet timed out.
1024
- nextDidTimeout = false ;
1025
1023
} else {
1026
1024
if ( ! nextState . alreadyCaptured ) {
1027
1025
// Since we haven't already suspended during this commit, clear the
1028
1026
// existing suspense state. We'll try rendering again.
1029
- nextDidTimeout = false ;
1030
1027
nextState = null ;
1031
1028
} else {
1032
1029
// Something in this boundary's subtree already suspended. Switch to
1033
1030
// rendering the fallback children. Set `alreadyCaptured` to true.
1034
- nextDidTimeout = true ;
1035
1031
if ( current !== null && nextState === current . memoizedState ) {
1036
1032
// Create a new suspense state to avoid mutating the current tree's.
1037
1033
nextState = {
@@ -1046,6 +1042,7 @@ function updateSuspenseComponent(
1046
1042
}
1047
1043
}
1048
1044
}
1045
+ const nextDidTimeout = nextState !== null && nextState . didTimeout ;
1049
1046
1050
1047
// This next part is a bit confusing. If the children timeout, we switch to
1051
1048
// showing the fallback children in place of the "primary" children.
@@ -1127,8 +1124,8 @@ function updateSuspenseComponent(
1127
1124
// its fragment. We're going to skip over these entirely.
1128
1125
const nextFallbackChildren = nextProps . fallback ;
1129
1126
const primaryChildFragment = createWorkInProgress (
1130
- currentFallbackChildFragment ,
1131
- currentFallbackChildFragment . pendingProps ,
1127
+ currentPrimaryChildFragment ,
1128
+ currentPrimaryChildFragment . pendingProps ,
1132
1129
NoWork ,
1133
1130
) ;
1134
1131
primaryChildFragment . effectTag |= Placement ;
@@ -1481,23 +1478,45 @@ function beginWork(
1481
1478
}
1482
1479
break ;
1483
1480
case SuspenseComponent : {
1484
- const child = bailoutOnAlreadyFinishedWork (
1485
- current ,
1486
- workInProgress ,
1487
- renderExpirationTime ,
1488
- ) ;
1489
- if ( child !== null ) {
1490
- const nextState = workInProgress . memoizedState ;
1491
- const nextDidTimeout = nextState !== null && nextState . didTimeout ;
1492
- if ( nextDidTimeout ) {
1493
- child . childExpirationTime = NoWork ;
1494
- return child . sibling ;
1481
+ const state : SuspenseState | null = workInProgress . memoizedState ;
1482
+ const didTimeout = state !== null && state . didTimeout ;
1483
+ if ( didTimeout ) {
1484
+ // If this boundary is currently timed out, we need to decide
1485
+ // whether to retry the primary children, or to skip over it and
1486
+ // go straight to the fallback. Check the priority of the primary
1487
+ // child fragment.
1488
+ const primaryChildFragment : Fiber = ( workInProgress . child : any ) ;
1489
+ const primaryChildExpirationTime =
1490
+ primaryChildFragment . childExpirationTime ;
1491
+ if (
1492
+ primaryChildExpirationTime !== NoWork &&
1493
+ primaryChildExpirationTime <= renderExpirationTime
1494
+ ) {
1495
+ // The primary children have pending work. Use the normal path
1496
+ // to attempt to render the primary children again.
1497
+ return updateSuspenseComponent (
1498
+ current ,
1499
+ workInProgress ,
1500
+ renderExpirationTime ,
1501
+ ) ;
1495
1502
} else {
1496
- return child ;
1503
+ // The primary children do not have pending work with sufficient
1504
+ // priority. Bailout.
1505
+ const child = bailoutOnAlreadyFinishedWork (
1506
+ current ,
1507
+ workInProgress ,
1508
+ renderExpirationTime ,
1509
+ ) ;
1510
+ if ( child !== null ) {
1511
+ // The fallback children have pending work. Skip over the
1512
+ // primary children and work on the fallback.
1513
+ return child . sibling ;
1514
+ } else {
1515
+ return null ;
1516
+ }
1497
1517
}
1498
- } else {
1499
- return null ;
1500
1518
}
1519
+ break ;
1501
1520
}
1502
1521
}
1503
1522
return bailoutOnAlreadyFinishedWork (
0 commit comments