File tree Expand file tree Collapse file tree 3 files changed +104
-0
lines changed
Expand file tree Collapse file tree 3 files changed +104
-0
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ " react-router " : patch
3+ ---
4+
5+ Handle ` dataStrategy ` implementations that return insufficient result sets by adding errors for routes without any available result
Original file line number Diff line number Diff line change 77} from "@testing-library/react" ;
88import * as React from "react" ;
99import type {
10+ DataStrategyResult ,
1011 ErrorResponse ,
1112 Fetcher ,
1213 Location ,
@@ -420,6 +421,78 @@ function testDomRouter(
420421 </div>"
421422 ` ) ;
422423 } ) ;
424+
425+ it ( "clears the HydrateFallback when dataStrategy returns partial results during hydration" , async ( ) => {
426+ let dfd = createDeferred < Record < string , DataStrategyResult > > ( ) ;
427+ let router = createTestRouter (
428+ [
429+ {
430+ id : "root" ,
431+ path : "/" ,
432+ loader : true ,
433+ HydrateFallback : ( ) => "Loading..." ,
434+ Component : ( ) => (
435+ < >
436+ < h1 > Root:{ useLoaderData ( ) } </ h1 >
437+ < Outlet />
438+ </ >
439+ ) ,
440+ ErrorBoundary : ( ) => {
441+ let error = useRouteError ( ) ;
442+ return (
443+ < pre >
444+ Root:
445+ { error instanceof Error ? error . message : ( error as string ) }
446+ </ pre >
447+ ) ;
448+ } ,
449+ children : [
450+ {
451+ id : "index" ,
452+ index : true ,
453+ loader : true ,
454+ Component : ( ) => < h2 > Index:{ useLoaderData ( ) } </ h2 > ,
455+ ErrorBoundary : ( ) => (
456+ < pre > Index:{ useRouteError ( ) as string } </ pre >
457+ ) ,
458+ } ,
459+ ] ,
460+ } ,
461+ ] ,
462+ {
463+ dataStrategy : ( ) => dfd . promise ,
464+ } ,
465+ ) ;
466+ let { container } = render ( < RouterProvider router = { router } /> ) ;
467+
468+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
469+ "<div>
470+ Loading...
471+ </div>"
472+ ` ) ;
473+
474+ // Resolve data strategy with only an error at the index route but nothing
475+ // for the root route
476+ await dfd . resolve ( {
477+ index : {
478+ type : "error" ,
479+ result : "INDEX ERROR" ,
480+ } ,
481+ } ) ;
482+ await tick ( ) ;
483+ await tick ( ) ;
484+
485+ // The router stubs in an error for the root route to get out of
486+ // displaying the HydrateFallback
487+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
488+ "<div>
489+ <pre>
490+ Root:
491+ No result returned from dataStrategy for route root
492+ </pre>
493+ </div>"
494+ ` ) ;
495+ } ) ;
423496 } ) ;
424497
425498 describe ( "navigations" , ( ) => {
Original file line number Diff line number Diff line change @@ -3042,6 +3042,32 @@ export function createRouter(init: RouterInit): Router {
30423042 return dataResults ;
30433043 }
30443044
3045+ // Stub errors where needed if they skipped returning data for routes
3046+ // above a route which returned an error. This is a problem if we don't
3047+ // already have data (or errors) for the ancestor route because we won't be
3048+ // able to render through that route in order to get down to the actual error
3049+ // returned on the descendant route
3050+ if ( ! isMutationMethod ( request . method ) ) {
3051+ for ( let match of matches ) {
3052+ if ( results [ match . route . id ] ?. type === ResultType . error ) {
3053+ break ;
3054+ }
3055+ if (
3056+ ! results . hasOwnProperty ( match . route . id ) &&
3057+ ! state . loaderData . hasOwnProperty ( match . route . id ) &&
3058+ ( ! state . errors || ! state . errors . hasOwnProperty ( match . route . id ) ) &&
3059+ match . shouldCallHandler ( )
3060+ ) {
3061+ results [ match . route . id ] = {
3062+ type : ResultType . error ,
3063+ result : new Error (
3064+ `No result returned from dataStrategy for route ${ match . route . id } ` ,
3065+ ) ,
3066+ } ;
3067+ }
3068+ }
3069+ }
3070+
30453071 for ( let [ routeId , result ] of Object . entries ( results ) ) {
30463072 if ( isRedirectDataStrategyResult ( result ) ) {
30473073 let response = result . result as Response ;
You can’t perform that action at this time.
0 commit comments