@@ -3108,6 +3108,81 @@ describe('ReactSuspenseWithNoopRenderer', () => {
31083108 } ,
31093109 ) ;
31103110
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+
31113186 it (
31123187 'regression: primary fragment fiber is not always part of setState ' +
31133188 'return path' ,
0 commit comments