@@ -2247,14 +2247,11 @@ describe('ReactDOMFizzServer', () => {
22472247 ) ;
22482248 }
22492249 await act ( async ( ) => {
2250- const { pipe} = ReactDOMFizzServer . renderToPipeableStream (
2251- < App fallbackText = "Loading..." /> ,
2252- {
2253- onError ( error ) {
2254- Scheduler . unstable_yieldValue ( '[s!] ' + error . message ) ;
2255- } ,
2250+ const { pipe} = ReactDOMFizzServer . renderToPipeableStream ( < App /> , {
2251+ onError ( error ) {
2252+ Scheduler . unstable_yieldValue ( '[s!] ' + error . message ) ;
22562253 } ,
2257- ) ;
2254+ } ) ;
22582255 pipe ( writable ) ;
22592256 } ) ;
22602257 expect ( Scheduler ) . toHaveYielded ( [ '[s!] Oops.' ] ) ;
@@ -2302,6 +2299,102 @@ describe('ReactDOMFizzServer', () => {
23022299 ) ;
23032300 } ) ;
23042301
2302+ // @gate experimental
2303+ it (
2304+ 'does not recreate the fallback if server errors and hydration suspends ' +
2305+ 'and root receives a transition' ,
2306+ async ( ) => {
2307+ let isClient = false ;
2308+
2309+ function Child ( { color} ) {
2310+ if ( isClient ) {
2311+ readText ( 'Yay!' ) ;
2312+ } else {
2313+ throw Error ( 'Oops.' ) ;
2314+ }
2315+ Scheduler . unstable_yieldValue ( 'Yay! (' + color + ')' ) ;
2316+ return 'Yay! (' + color + ')' ;
2317+ }
2318+
2319+ const fallbackRef = React . createRef ( ) ;
2320+ function App ( { color} ) {
2321+ return (
2322+ < div >
2323+ < Suspense fallback = { < p ref = { fallbackRef } > Loading...</ p > } >
2324+ < span >
2325+ < Child color = { color } />
2326+ </ span >
2327+ </ Suspense >
2328+ </ div >
2329+ ) ;
2330+ }
2331+ await act ( async ( ) => {
2332+ const { pipe} = ReactDOMFizzServer . renderToPipeableStream (
2333+ < App color = "red" /> ,
2334+ {
2335+ onError ( error ) {
2336+ Scheduler . unstable_yieldValue ( '[s!] ' + error . message ) ;
2337+ } ,
2338+ } ,
2339+ ) ;
2340+ pipe ( writable ) ;
2341+ } ) ;
2342+ expect ( Scheduler ) . toHaveYielded ( [ '[s!] Oops.' ] ) ;
2343+
2344+ // The server could not complete this boundary, so we'll retry on the client.
2345+ const serverFallback = container . getElementsByTagName ( 'p' ) [ 0 ] ;
2346+ expect ( serverFallback . innerHTML ) . toBe ( 'Loading...' ) ;
2347+
2348+ // Hydrate the tree. This will suspend.
2349+ isClient = true ;
2350+ const root = ReactDOMClient . hydrateRoot ( container , < App color = "red" /> , {
2351+ onRecoverableError ( error ) {
2352+ Scheduler . unstable_yieldValue ( '[c!] ' + error . message ) ;
2353+ } ,
2354+ } ) ;
2355+ // This should not report any errors yet.
2356+ expect ( Scheduler ) . toFlushAndYield ( [ ] ) ;
2357+ expect ( getVisibleChildren ( container ) ) . toEqual (
2358+ < div >
2359+ < p > Loading...</ p >
2360+ </ div > ,
2361+ ) ;
2362+
2363+ // Normally, hydrating after server error would force a clean client render.
2364+ // However, it suspended so at best we'd only get the same fallback anyway.
2365+ // We don't want to recreate the same fallback in the DOM again because
2366+ // that's extra work and would restart animations etc. Check we don't do that.
2367+ const clientFallback = container . getElementsByTagName ( 'p' ) [ 0 ] ;
2368+ expect ( serverFallback ) . toBe ( clientFallback ) ;
2369+
2370+ // Transition updates shouldn't recreate the fallback either.
2371+ React . startTransition ( ( ) => {
2372+ root . render ( < App color = "blue" /> ) ;
2373+ } ) ;
2374+ Scheduler . unstable_flushAll ( ) ;
2375+ jest . runAllTimers ( ) ;
2376+ const clientFallback2 = container . getElementsByTagName ( 'p' ) [ 0 ] ;
2377+ expect ( clientFallback2 ) . toBe ( serverFallback ) ;
2378+
2379+ // When we're able to fully hydrate, we expect a clean client render.
2380+ await act ( async ( ) => {
2381+ resolveText ( 'Yay!' ) ;
2382+ } ) ;
2383+ expect ( Scheduler ) . toFlushAndYield ( [
2384+ 'Yay! (red)' ,
2385+ '[c!] The server could not finish this Suspense boundary, ' +
2386+ 'likely due to an error during server rendering. ' +
2387+ 'Switched to client rendering.' ,
2388+ 'Yay! (blue)' ,
2389+ ] ) ;
2390+ expect ( getVisibleChildren ( container ) ) . toEqual (
2391+ < div >
2392+ < span > Yay! (blue)</ span >
2393+ </ div > ,
2394+ ) ;
2395+ } ,
2396+ ) ;
2397+
23052398 // @gate experimental
23062399 it (
23072400 'recreates the fallback if server errors and hydration suspends but ' +
0 commit comments