@@ -3108,6 +3108,81 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3108
3108
} ,
3109
3109
) ;
3110
3110
3111
+ it (
3112
+ 'fallback component can update itself even after a high pri update to ' +
3113
+ 'the primary tree suspends' ,
3114
+ async ( ) => {
3115
+ const { useState} = React ;
3116
+ const root = ReactNoop . createRoot ( ) ;
3117
+
3118
+ let setAppText ;
3119
+ function App ( ) {
3120
+ const [ text , _setText ] = useState ( 'A' ) ;
3121
+ setAppText = _setText ;
3122
+ return (
3123
+ < >
3124
+ < Suspense fallback = { < Fallback /> } >
3125
+ < AsyncText text = { text } />
3126
+ </ Suspense >
3127
+ </ >
3128
+ ) ;
3129
+ }
3130
+
3131
+ let setFallbackText ;
3132
+ function Fallback ( ) {
3133
+ const [ text , _setText ] = useState ( 'Loading...' ) ;
3134
+ setFallbackText = _setText ;
3135
+ return < Text text = { text } /> ;
3136
+ }
3137
+
3138
+ // Resolve the initial tree
3139
+ await resolveText ( 'A' ) ;
3140
+ await ReactNoop . act ( async ( ) => {
3141
+ root . render ( < App /> ) ;
3142
+ } ) ;
3143
+ expect ( Scheduler ) . toHaveYielded ( [ 'A' ] ) ;
3144
+ expect ( root ) . toMatchRenderedOutput ( < span prop = "A" /> ) ;
3145
+
3146
+ // Schedule an update inside the Suspense boundary that suspends.
3147
+ await ReactNoop . act ( async ( ) => {
3148
+ setAppText ( 'B' ) ;
3149
+ } ) ;
3150
+ expect ( Scheduler ) . toHaveYielded ( [ 'Suspend! [B]' , 'Loading...' ] ) ;
3151
+ // Commit the placeholder
3152
+ await advanceTimers ( 250 ) ;
3153
+ expect ( root ) . toMatchRenderedOutput (
3154
+ < >
3155
+ < span hidden = { true } prop = "A" />
3156
+ < span prop = "Loading..." />
3157
+ </ > ,
3158
+ ) ;
3159
+
3160
+ // Schedule a high pri update on the boundary, and a lower pri update
3161
+ // on the fallback. We're testing to make sure the fallback can still
3162
+ // update even though the primary tree is suspended.
3163
+ await ReactNoop . act ( async ( ) => {
3164
+ ReactNoop . discreteUpdates ( ( ) => {
3165
+ setAppText ( 'C' ) ;
3166
+ } ) ;
3167
+ setFallbackText ( 'Still loading...' ) ;
3168
+ } ) ;
3169
+
3170
+ expect ( Scheduler ) . toHaveYielded ( [
3171
+ // First try to update the suspended tree. It's still suspended.
3172
+ 'Suspend! [C]' ,
3173
+ 'Loading...' ,
3174
+ // Then complete the update to the fallback.
3175
+ 'Still loading...' ,
3176
+ ] ) ;
3177
+ expect ( root ) . toMatchRenderedOutput (
3178
+ < >
3179
+ < span hidden = { true } prop = "A" />
3180
+ < span prop = "Still loading..." />
3181
+ </ > ,
3182
+ ) ;
3183
+ } ,
3184
+ ) ;
3185
+
3111
3186
it (
3112
3187
'regression: primary fragment fiber is not always part of setState ' +
3113
3188
'return path' ,
0 commit comments