Skip to content

Commit 37eb416

Browse files
authored
fix(router-core): Catch errors thrown during hydrate (#5686)
1 parent 1bdcc9d commit 37eb416

File tree

13 files changed

+708
-45
lines changed

13 files changed

+708
-45
lines changed

e2e/react-start/basic/src/routeTree.gen.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { Route as SearchParamsDefaultRouteImport } from './routes/search-params/
3434
import { Route as RedirectTargetRouteImport } from './routes/redirect/$target'
3535
import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
3636
import { Route as NotFoundViaLoaderRouteImport } from './routes/not-found/via-loader'
37+
import { Route as NotFoundViaHeadRouteImport } from './routes/not-found/via-head'
3738
import { Route as NotFoundViaBeforeLoadRouteImport } from './routes/not-found/via-beforeLoad'
3839
import { Route as ApiUsersRouteImport } from './routes/api.users'
3940
import { Route as LayoutLayout2RouteImport } from './routes/_layout/_layout-2'
@@ -169,6 +170,11 @@ const NotFoundViaLoaderRoute = NotFoundViaLoaderRouteImport.update({
169170
path: '/via-loader',
170171
getParentRoute: () => NotFoundRouteRoute,
171172
} as any)
173+
const NotFoundViaHeadRoute = NotFoundViaHeadRouteImport.update({
174+
id: '/via-head',
175+
path: '/via-head',
176+
getParentRoute: () => NotFoundRouteRoute,
177+
} as any)
172178
const NotFoundViaBeforeLoadRoute = NotFoundViaBeforeLoadRouteImport.update({
173179
id: '/via-beforeLoad',
174180
path: '/via-beforeLoad',
@@ -272,6 +278,7 @@ export interface FileRoutesByFullPath {
272278
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
273279
'/api/users': typeof ApiUsersRouteWithChildren
274280
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
281+
'/not-found/via-head': typeof NotFoundViaHeadRoute
275282
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
276283
'/posts/$postId': typeof PostsPostIdRoute
277284
'/redirect/$target': typeof RedirectTargetRouteWithChildren
@@ -307,6 +314,7 @@ export interface FileRoutesByTo {
307314
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
308315
'/api/users': typeof ApiUsersRouteWithChildren
309316
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
317+
'/not-found/via-head': typeof NotFoundViaHeadRoute
310318
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
311319
'/posts/$postId': typeof PostsPostIdRoute
312320
'/search-params/default': typeof SearchParamsDefaultRoute
@@ -347,6 +355,7 @@ export interface FileRoutesById {
347355
'/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
348356
'/api/users': typeof ApiUsersRouteWithChildren
349357
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
358+
'/not-found/via-head': typeof NotFoundViaHeadRoute
350359
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
351360
'/posts/$postId': typeof PostsPostIdRoute
352361
'/redirect/$target': typeof RedirectTargetRouteWithChildren
@@ -389,6 +398,7 @@ export interface FileRouteTypes {
389398
| '/대한민국'
390399
| '/api/users'
391400
| '/not-found/via-beforeLoad'
401+
| '/not-found/via-head'
392402
| '/not-found/via-loader'
393403
| '/posts/$postId'
394404
| '/redirect/$target'
@@ -424,6 +434,7 @@ export interface FileRouteTypes {
424434
| '/대한민국'
425435
| '/api/users'
426436
| '/not-found/via-beforeLoad'
437+
| '/not-found/via-head'
427438
| '/not-found/via-loader'
428439
| '/posts/$postId'
429440
| '/search-params/default'
@@ -463,6 +474,7 @@ export interface FileRouteTypes {
463474
| '/_layout/_layout-2'
464475
| '/api/users'
465476
| '/not-found/via-beforeLoad'
477+
| '/not-found/via-head'
466478
| '/not-found/via-loader'
467479
| '/posts/$postId'
468480
| '/redirect/$target'
@@ -673,6 +685,13 @@ declare module '@tanstack/react-router' {
673685
preLoaderRoute: typeof NotFoundViaLoaderRouteImport
674686
parentRoute: typeof NotFoundRouteRoute
675687
}
688+
'/not-found/via-head': {
689+
id: '/not-found/via-head'
690+
path: '/via-head'
691+
fullPath: '/not-found/via-head'
692+
preLoaderRoute: typeof NotFoundViaHeadRouteImport
693+
parentRoute: typeof NotFoundRouteRoute
694+
}
676695
'/not-found/via-beforeLoad': {
677696
id: '/not-found/via-beforeLoad'
678697
path: '/via-beforeLoad'
@@ -797,12 +816,14 @@ declare module '@tanstack/react-router' {
797816

798817
interface NotFoundRouteRouteChildren {
799818
NotFoundViaBeforeLoadRoute: typeof NotFoundViaBeforeLoadRoute
819+
NotFoundViaHeadRoute: typeof NotFoundViaHeadRoute
800820
NotFoundViaLoaderRoute: typeof NotFoundViaLoaderRoute
801821
NotFoundIndexRoute: typeof NotFoundIndexRoute
802822
}
803823

804824
const NotFoundRouteRouteChildren: NotFoundRouteRouteChildren = {
805825
NotFoundViaBeforeLoadRoute: NotFoundViaBeforeLoadRoute,
826+
NotFoundViaHeadRoute: NotFoundViaHeadRoute,
806827
NotFoundViaLoaderRoute: NotFoundViaLoaderRoute,
807828
NotFoundIndexRoute: NotFoundIndexRoute,
808829
}

e2e/react-start/basic/src/routes/not-found/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export const Route = createFileRoute('/not-found/')({
2525
via-loader
2626
</Link>
2727
</div>
28+
<div className="mb-2">
29+
<Link
30+
from={Route.fullPath}
31+
to="./via-head"
32+
preload={preload}
33+
data-testid="via-head"
34+
>
35+
via-head
36+
</Link>
37+
</div>
2838
</div>
2939
)
3040
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createFileRoute, notFound } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/not-found/via-head')({
4+
head: () => {
5+
throw notFound()
6+
},
7+
component: RouteComponent,
8+
notFoundComponent: () => {
9+
return (
10+
<div data-testid="via-head-notFound-component">
11+
Not Found "/not-found/via-head"!
12+
</div>
13+
)
14+
},
15+
})
16+
17+
function RouteComponent() {
18+
return (
19+
<div data-testid="via-head-route-component" data-server={typeof window}>
20+
Hello "/not-found/via-head"!
21+
</div>
22+
)
23+
}

e2e/react-start/basic/tests/not-found.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const combinate = (combinateImport as any).default as typeof combinateImport
99
test.use({
1010
whitelistErrors: [
1111
/Failed to load resource: the server responded with a status of 404/,
12+
'NotFound error during hydration for routeId',
1213
],
1314
})
1415
test.describe('not-found', () => {
@@ -25,7 +26,7 @@ test.describe('not-found', () => {
2526
test.describe('throw notFound()', () => {
2627
const navigationTestMatrix = combinate({
2728
// TODO beforeLoad!
28-
thrower: [/* 'beforeLoad',*/ 'loader'] as const,
29+
thrower: [/* 'beforeLoad',*/ 'head', 'loader'] as const,
2930
preload: [false, true] as const,
3031
})
3132

@@ -57,7 +58,7 @@ test.describe('not-found', () => {
5758
const directVisitTestMatrix = combinate({
5859
// TODO beforeLoad!
5960

60-
thrower: [/* 'beforeLoad',*/ 'loader'] as const,
61+
thrower: [/* 'beforeLoad',*/ 'head', 'loader'] as const,
6162
})
6263

6364
directVisitTestMatrix.forEach(({ thrower }) => {

e2e/react-start/basic/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const prerenderConfiguration = {
2020
'/redirect',
2121
'/i-do-not-exist',
2222
'/not-found/via-beforeLoad',
23+
'/not-found/via-head',
2324
'/not-found/via-loader',
2425
'/users',
2526
].some((p) => page.path.includes(p)),

e2e/solid-start/basic/src/routeTree.gen.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { Route as SearchParamsDefaultRouteImport } from './routes/search-params/
3232
import { Route as RedirectTargetRouteImport } from './routes/redirect/$target'
3333
import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
3434
import { Route as NotFoundViaLoaderRouteImport } from './routes/not-found/via-loader'
35+
import { Route as NotFoundViaHeadRouteImport } from './routes/not-found/via-head'
3536
import { Route as NotFoundViaBeforeLoadRouteImport } from './routes/not-found/via-beforeLoad'
3637
import { Route as ApiUsersRouteImport } from './routes/api/users'
3738
import { Route as LayoutLayout2RouteImport } from './routes/_layout/_layout-2'
@@ -165,6 +166,11 @@ const NotFoundViaLoaderRoute = NotFoundViaLoaderRouteImport.update({
165166
path: '/via-loader',
166167
getParentRoute: () => NotFoundRouteRoute,
167168
} as any)
169+
const NotFoundViaHeadRoute = NotFoundViaHeadRouteImport.update({
170+
id: '/via-head',
171+
path: '/via-head',
172+
getParentRoute: () => NotFoundRouteRoute,
173+
} as any)
168174
const NotFoundViaBeforeLoadRoute = NotFoundViaBeforeLoadRouteImport.update({
169175
id: '/via-beforeLoad',
170176
path: '/via-beforeLoad',
@@ -266,6 +272,7 @@ export interface FileRoutesByFullPath {
266272
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
267273
'/api/users': typeof ApiUsersRouteWithChildren
268274
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
275+
'/not-found/via-head': typeof NotFoundViaHeadRoute
269276
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
270277
'/posts/$postId': typeof PostsPostIdRoute
271278
'/redirect/$target': typeof RedirectTargetRouteWithChildren
@@ -301,6 +308,7 @@ export interface FileRoutesByTo {
301308
'/대한민국': typeof Char45824Char54620Char48124Char44397Route
302309
'/api/users': typeof ApiUsersRouteWithChildren
303310
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
311+
'/not-found/via-head': typeof NotFoundViaHeadRoute
304312
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
305313
'/posts/$postId': typeof PostsPostIdRoute
306314
'/search-params/default': typeof SearchParamsDefaultRoute
@@ -342,6 +350,7 @@ export interface FileRoutesById {
342350
'/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
343351
'/api/users': typeof ApiUsersRouteWithChildren
344352
'/not-found/via-beforeLoad': typeof NotFoundViaBeforeLoadRoute
353+
'/not-found/via-head': typeof NotFoundViaHeadRoute
345354
'/not-found/via-loader': typeof NotFoundViaLoaderRoute
346355
'/posts/$postId': typeof PostsPostIdRoute
347356
'/redirect/$target': typeof RedirectTargetRouteWithChildren
@@ -383,6 +392,7 @@ export interface FileRouteTypes {
383392
| '/대한민국'
384393
| '/api/users'
385394
| '/not-found/via-beforeLoad'
395+
| '/not-found/via-head'
386396
| '/not-found/via-loader'
387397
| '/posts/$postId'
388398
| '/redirect/$target'
@@ -418,6 +428,7 @@ export interface FileRouteTypes {
418428
| '/대한민국'
419429
| '/api/users'
420430
| '/not-found/via-beforeLoad'
431+
| '/not-found/via-head'
421432
| '/not-found/via-loader'
422433
| '/posts/$postId'
423434
| '/search-params/default'
@@ -458,6 +469,7 @@ export interface FileRouteTypes {
458469
| '/_layout/_layout-2'
459470
| '/api/users'
460471
| '/not-found/via-beforeLoad'
472+
| '/not-found/via-head'
461473
| '/not-found/via-loader'
462474
| '/posts/$postId'
463475
| '/redirect/$target'
@@ -668,6 +680,13 @@ declare module '@tanstack/solid-router' {
668680
preLoaderRoute: typeof NotFoundViaLoaderRouteImport
669681
parentRoute: typeof NotFoundRouteRoute
670682
}
683+
'/not-found/via-head': {
684+
id: '/not-found/via-head'
685+
path: '/via-head'
686+
fullPath: '/not-found/via-head'
687+
preLoaderRoute: typeof NotFoundViaHeadRouteImport
688+
parentRoute: typeof NotFoundRouteRoute
689+
}
671690
'/not-found/via-beforeLoad': {
672691
id: '/not-found/via-beforeLoad'
673692
path: '/via-beforeLoad'
@@ -785,12 +804,14 @@ declare module '@tanstack/solid-router' {
785804

786805
interface NotFoundRouteRouteChildren {
787806
NotFoundViaBeforeLoadRoute: typeof NotFoundViaBeforeLoadRoute
807+
NotFoundViaHeadRoute: typeof NotFoundViaHeadRoute
788808
NotFoundViaLoaderRoute: typeof NotFoundViaLoaderRoute
789809
NotFoundIndexRoute: typeof NotFoundIndexRoute
790810
}
791811

792812
const NotFoundRouteRouteChildren: NotFoundRouteRouteChildren = {
793813
NotFoundViaBeforeLoadRoute: NotFoundViaBeforeLoadRoute,
814+
NotFoundViaHeadRoute: NotFoundViaHeadRoute,
794815
NotFoundViaLoaderRoute: NotFoundViaLoaderRoute,
795816
NotFoundIndexRoute: NotFoundIndexRoute,
796817
}

e2e/solid-start/basic/src/routes/not-found/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export const Route = createFileRoute('/not-found/')({
2525
via-loader
2626
</Link>
2727
</div>
28+
<div class="mb-2">
29+
<Link
30+
from={Route.fullPath}
31+
to="./via-head"
32+
preload={preload()}
33+
data-testid="via-head"
34+
>
35+
via-head
36+
</Link>
37+
</div>
2838
</div>
2939
)
3040
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createFileRoute, notFound } from '@tanstack/solid-router'
2+
3+
export const Route = createFileRoute('/not-found/via-head')({
4+
head: () => {
5+
throw notFound()
6+
},
7+
component: RouteComponent,
8+
notFoundComponent: () => {
9+
return (
10+
<div data-testid="via-head-notFound-component">
11+
Not Found "/not-found/via-head"!
12+
</div>
13+
)
14+
},
15+
})
16+
17+
function RouteComponent() {
18+
return (
19+
<div data-testid="via-head-route-component" data-server={typeof window}>
20+
Hello "/not-found/via-head"!
21+
</div>
22+
)
23+
}

e2e/solid-start/basic/tests/not-found.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const combinate = (combinateImport as any).default as typeof combinateImport
99
test.use({
1010
whitelistErrors: [
1111
/Failed to load resource: the server responded with a status of 404/,
12+
'NotFound error during hydration for routeId',
1213
],
1314
})
1415
test.describe('not-found', () => {
@@ -25,7 +26,7 @@ test.describe('not-found', () => {
2526
test.describe('throw notFound()', () => {
2627
const navigationTestMatrix = combinate({
2728
// TODO beforeLoad!
28-
thrower: [/* 'beforeLoad',*/ 'loader'] as const,
29+
thrower: [/* 'beforeLoad',*/ 'head', 'loader'] as const,
2930
preload: [false, true] as const,
3031
})
3132

@@ -56,7 +57,7 @@ test.describe('not-found', () => {
5657
const directVisitTestMatrix = combinate({
5758
// TODO beforeLoad!
5859

59-
thrower: [/* 'beforeLoad',*/ 'loader'] as const,
60+
thrower: [/* 'beforeLoad',*/ 'head', 'loader'] as const,
6061
})
6162

6263
directVisitTestMatrix.forEach(({ thrower }) => {

e2e/solid-start/basic/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const prerenderConfiguration = {
2020
'/redirect',
2121
'/i-do-not-exist',
2222
'/not-found/via-beforeLoad',
23+
'/not-found/via-head',
2324
'/not-found/via-loader',
2425
'/search-params/default',
2526
'/transition',

0 commit comments

Comments
 (0)