@@ -280,6 +280,7 @@ import {
280
280
createCapturedValueFromError ,
281
281
createCapturedValueAtFiber ,
282
282
} from './ReactCapturedValue' ;
283
+ import { OffscreenVisible } from './ReactFiberOffscreenComponent' ;
283
284
import {
284
285
createClassErrorUpdate ,
285
286
initializeClassErrorUpdate ,
@@ -620,6 +621,18 @@ function updateOffscreenComponent(
620
621
const prevState : OffscreenState | null =
621
622
current !== null ? current . memoizedState : null ;
622
623
624
+ if ( current === null && workInProgress . stateNode === null ) {
625
+ // We previously reset the work-in-progress.
626
+ // We need to create a new Offscreen instance.
627
+ const primaryChildInstance : OffscreenInstance = {
628
+ _visibility : OffscreenVisible ,
629
+ _pendingMarkers : null ,
630
+ _retryCache : null ,
631
+ _transitions : null ,
632
+ } ;
633
+ workInProgress . stateNode = primaryChildInstance ;
634
+ }
635
+
623
636
if (
624
637
nextProps . mode === 'hidden' ||
625
638
( enableLegacyHidden && nextProps . mode === 'unstable-defer-without-hiding' )
@@ -788,6 +801,26 @@ function updateOffscreenComponent(
788
801
return workInProgress . child ;
789
802
}
790
803
804
+ function bailoutOffscreenComponent (
805
+ current : Fiber | null ,
806
+ workInProgress : Fiber ,
807
+ ) : Fiber | null {
808
+ if (
809
+ ( current === null || current . tag !== OffscreenComponent ) &&
810
+ workInProgress . stateNode === null
811
+ ) {
812
+ const primaryChildInstance : OffscreenInstance = {
813
+ _visibility : OffscreenVisible ,
814
+ _pendingMarkers : null ,
815
+ _retryCache : null ,
816
+ _transitions : null ,
817
+ } ;
818
+ workInProgress . stateNode = primaryChildInstance ;
819
+ }
820
+
821
+ return workInProgress . sibling ;
822
+ }
823
+
791
824
function deferHiddenOffscreenComponent (
792
825
current : Fiber | null ,
793
826
workInProgress : Fiber ,
@@ -1095,9 +1128,13 @@ function updateActivityComponent(
1095
1128
if ( nextProps . mode === 'hidden' ) {
1096
1129
// SSR doesn't render hidden Activity so it shouldn't hydrate,
1097
1130
// even at offscreen lane. Defer to a client rendered offscreen lane.
1098
- mountActivityChildren ( workInProgress , nextProps , renderLanes ) ;
1131
+ const primaryChildFragment = mountActivityChildren (
1132
+ workInProgress ,
1133
+ nextProps ,
1134
+ renderLanes ,
1135
+ ) ;
1099
1136
workInProgress . lanes = laneToLanes ( OffscreenLane ) ;
1100
- return null ;
1137
+ return bailoutOffscreenComponent ( null , primaryChildFragment ) ;
1101
1138
} else {
1102
1139
// We must push the suspense handler context *before* attempting to
1103
1140
// hydrate, to avoid a mismatch in case it errors.
@@ -2373,7 +2410,7 @@ function updateSuspenseComponent(
2373
2410
if ( showFallback ) {
2374
2411
pushFallbackTreeSuspenseHandler ( workInProgress ) ;
2375
2412
2376
- const fallbackFragment = mountSuspenseFallbackChildren (
2413
+ mountSuspenseFallbackChildren (
2377
2414
workInProgress ,
2378
2415
nextPrimaryChildren ,
2379
2416
nextFallbackChildren ,
@@ -2408,7 +2445,7 @@ function updateSuspenseComponent(
2408
2445
}
2409
2446
}
2410
2447
2411
- return fallbackFragment ;
2448
+ return bailoutOffscreenComponent ( null , primaryChildFragment ) ;
2412
2449
} else if (
2413
2450
enableCPUSuspense &&
2414
2451
typeof nextProps . unstable_expectedLoadTime === 'number'
@@ -2417,7 +2454,7 @@ function updateSuspenseComponent(
2417
2454
// unblock the surrounding content. Then immediately retry after the
2418
2455
// initial commit.
2419
2456
pushFallbackTreeSuspenseHandler ( workInProgress ) ;
2420
- const fallbackFragment = mountSuspenseFallbackChildren (
2457
+ mountSuspenseFallbackChildren (
2421
2458
workInProgress ,
2422
2459
nextPrimaryChildren ,
2423
2460
nextFallbackChildren ,
@@ -2444,7 +2481,7 @@ function updateSuspenseComponent(
2444
2481
// RetryLane even if it's the one currently rendering since we're leaving
2445
2482
// it behind on this node.
2446
2483
workInProgress . lanes = SomeRetryLane ;
2447
- return fallbackFragment ;
2484
+ return bailoutOffscreenComponent ( null , primaryChildFragment ) ;
2448
2485
} else {
2449
2486
pushPrimaryTreeSuspenseHandler ( workInProgress ) ;
2450
2487
return mountSuspensePrimaryChildren (
@@ -2479,7 +2516,7 @@ function updateSuspenseComponent(
2479
2516
2480
2517
const nextFallbackChildren = nextProps . fallback ;
2481
2518
const nextPrimaryChildren = nextProps . children ;
2482
- const fallbackChildFragment = updateSuspenseFallbackChildren (
2519
+ updateSuspenseFallbackChildren (
2483
2520
current ,
2484
2521
workInProgress ,
2485
2522
nextPrimaryChildren ,
@@ -2532,7 +2569,7 @@ function updateSuspenseComponent(
2532
2569
renderLanes ,
2533
2570
) ;
2534
2571
workInProgress . memoizedState = SUSPENDED_MARKER ;
2535
- return fallbackChildFragment ;
2572
+ return bailoutOffscreenComponent ( current . child , primaryChildFragment ) ;
2536
2573
} else {
2537
2574
if (
2538
2575
prevState !== null &&
@@ -2788,7 +2825,7 @@ function updateSuspenseFallbackChildren(
2788
2825
primaryChildFragment . sibling = fallbackChildFragment ;
2789
2826
workInProgress . child = primaryChildFragment ;
2790
2827
2791
- return fallbackChildFragment ;
2828
+ return bailoutOffscreenComponent ( null , primaryChildFragment ) ;
2792
2829
}
2793
2830
2794
2831
function retrySuspenseComponentWithoutHydrating (
@@ -3094,14 +3131,13 @@ function updateDehydratedSuspenseComponent(
3094
3131
3095
3132
const nextPrimaryChildren = nextProps . children ;
3096
3133
const nextFallbackChildren = nextProps . fallback ;
3097
- const fallbackChildFragment =
3098
- mountSuspenseFallbackAfterRetryWithoutHydrating (
3099
- current ,
3100
- workInProgress ,
3101
- nextPrimaryChildren ,
3102
- nextFallbackChildren ,
3103
- renderLanes ,
3104
- ) ;
3134
+ mountSuspenseFallbackAfterRetryWithoutHydrating (
3135
+ current ,
3136
+ workInProgress ,
3137
+ nextPrimaryChildren ,
3138
+ nextFallbackChildren ,
3139
+ renderLanes ,
3140
+ ) ;
3105
3141
const primaryChildFragment : Fiber = ( workInProgress . child : any ) ;
3106
3142
primaryChildFragment . memoizedState =
3107
3143
mountSuspenseOffscreenState ( renderLanes ) ;
@@ -3111,7 +3147,7 @@ function updateDehydratedSuspenseComponent(
3111
3147
renderLanes ,
3112
3148
) ;
3113
3149
workInProgress . memoizedState = SUSPENDED_MARKER ;
3114
- return fallbackChildFragment ;
3150
+ return bailoutOffscreenComponent ( null , primaryChildFragment ) ;
3115
3151
}
3116
3152
}
3117
3153
}
0 commit comments