@@ -1632,12 +1632,28 @@ function updateSuspenseComponent(
1632
1632
}
1633
1633
1634
1634
function retrySuspenseComponentWithoutHydrating (
1635
- current : Fiber ,
1635
+ current : Fiber | null ,
1636
1636
workInProgress : Fiber ,
1637
1637
renderExpirationTime : ExpirationTime ,
1638
1638
) {
1639
+ let fiberToDelete = current ;
1640
+ if ( fiberToDelete === null ) {
1641
+ // We're going to delete the dehydrated boundary but we don't have a
1642
+ // current. To be able to insert something in the deletion list we
1643
+ // to create one. That's because our workInProgress is going to be
1644
+ // upgraded so we can't use that one.
1645
+ fiberToDelete = createWorkInProgress (
1646
+ workInProgress ,
1647
+ workInProgress . pendingProps ,
1648
+ renderExpirationTime ,
1649
+ ) ;
1650
+ fiberToDelete . return = workInProgress . return ;
1651
+ } else {
1652
+ // This is now an insertion.
1653
+ workInProgress . effectTag |= Placement ;
1654
+ }
1639
1655
// Detach from the current dehydrated boundary.
1640
- current . alternate = null ;
1656
+ fiberToDelete . alternate = null ;
1641
1657
workInProgress . alternate = null ;
1642
1658
1643
1659
// Insert a deletion in the effect list.
@@ -1649,20 +1665,18 @@ function retrySuspenseComponentWithoutHydrating(
1649
1665
) ;
1650
1666
const last = returnFiber . lastEffect ;
1651
1667
if ( last !== null ) {
1652
- last . nextEffect = current ;
1653
- returnFiber . lastEffect = current ;
1668
+ last . nextEffect = fiberToDelete ;
1669
+ returnFiber . lastEffect = fiberToDelete ;
1654
1670
} else {
1655
- returnFiber . firstEffect = returnFiber . lastEffect = current ;
1671
+ returnFiber . firstEffect = returnFiber . lastEffect = fiberToDelete ;
1656
1672
}
1657
- current . nextEffect = null ;
1658
- current . effectTag = Deletion ;
1673
+ fiberToDelete . nextEffect = null ;
1674
+ fiberToDelete . effectTag = Deletion ;
1659
1675
1660
1676
// Upgrade this work in progress to a real Suspense component.
1661
1677
workInProgress . tag = SuspenseComponent ;
1662
1678
workInProgress . stateNode = null ;
1663
1679
workInProgress . memoizedState = null ;
1664
- // This is now an insertion.
1665
- workInProgress . effectTag |= Placement ;
1666
1680
// Retry as a real Suspense component.
1667
1681
return updateSuspenseComponent ( null , workInProgress , renderExpirationTime ) ;
1668
1682
}
@@ -1672,6 +1686,17 @@ function updateDehydratedSuspenseComponent(
1672
1686
workInProgress : Fiber ,
1673
1687
renderExpirationTime : ExpirationTime ,
1674
1688
) {
1689
+ const suspenseInstance = ( workInProgress . stateNode : SuspenseInstance ) ;
1690
+ if ( isSuspenseInstanceFallback ( suspenseInstance ) ) {
1691
+ // This boundary is in a permanent fallback state. In this case, we'll never
1692
+ // get an update and we'll never be able to hydrate the final content. Let's just try the
1693
+ // client side render instead.
1694
+ return retrySuspenseComponentWithoutHydrating (
1695
+ current ,
1696
+ workInProgress ,
1697
+ renderExpirationTime ,
1698
+ ) ;
1699
+ }
1675
1700
if ( current === null ) {
1676
1701
// During the first pass, we'll bail out and not drill into the children.
1677
1702
// Instead, we'll leave the content in place and try to hydrate it later.
@@ -1684,17 +1709,6 @@ function updateDehydratedSuspenseComponent(
1684
1709
workInProgress . child = null ;
1685
1710
return null ;
1686
1711
}
1687
- const suspenseInstance = ( current . stateNode : SuspenseInstance ) ;
1688
- if ( isSuspenseInstanceFallback ( suspenseInstance ) ) {
1689
- // This boundary is in a permanent fallback state. In this case, we'll never
1690
- // get an update and we'll never be able to hydrate the final content. Let's just try the
1691
- // client side render instead.
1692
- return retrySuspenseComponentWithoutHydrating (
1693
- current ,
1694
- workInProgress ,
1695
- renderExpirationTime ,
1696
- ) ;
1697
- }
1698
1712
// We use childExpirationTime to indicate that a child might depend on context, so if
1699
1713
// any context has changed, we need to treat is as if the input might have changed.
1700
1714
const hasContextChanged = current . childExpirationTime >= renderExpirationTime ;
0 commit comments