@tanstack/react-router 0.0.1-beta.2 → 0.0.1-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.2",
4
+ "version": "0.0.1-beta.21",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router/",
@@ -34,13 +34,14 @@
34
34
  "build/**",
35
35
  "src"
36
36
  ],
37
+ "sideEffects": false,
37
38
  "peerDependencies": {
38
39
  "react": ">=16",
39
40
  "react-dom": ">=16"
40
41
  },
41
42
  "dependencies": {
42
43
  "@babel/runtime": "^7.16.7",
43
- "@tanstack/router-core": "0.0.1-beta.2",
44
+ "@tanstack/router-core": "0.0.1-beta.21",
44
45
  "use-sync-external-store": "^1.2.0"
45
46
  },
46
47
  "devDependencies": {
package/src/index.tsx CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  AnyRoute,
7
7
  CheckId,
8
8
  rootRouteId,
9
- Router,
9
+ Route,
10
10
  RouterState,
11
11
  ToIdOption,
12
12
  } from '@tanstack/router-core'
@@ -31,15 +31,119 @@ import {
31
31
  NoInfer,
32
32
  ToOptions,
33
33
  invariant,
34
+ Router,
34
35
  } from '@tanstack/router-core'
35
36
 
36
37
  export * from '@tanstack/router-core'
37
38
 
39
+ export interface RegisterRouter {
40
+ // router: Router
41
+ }
42
+
43
+ export type RegisteredRouter = RegisterRouter extends {
44
+ router: Router<infer TRouteConfig, infer TAllRouteInfo>
45
+ }
46
+ ? Router<TRouteConfig, TAllRouteInfo>
47
+ : Router
48
+
49
+ export type RegisteredAllRouteInfo = RegisterRouter extends {
50
+ router: Router<infer TRouteConfig, infer TAllRouteInfo>
51
+ }
52
+ ? TAllRouteInfo
53
+ : AnyAllRouteInfo
54
+
55
+ export type SyncRouteComponent = (props?: {}) => JSX.Element | React.ReactNode
56
+
57
+ export type RouteComponent = SyncRouteComponent & {
58
+ preload?: () => Promise<SyncRouteComponent>
59
+ }
60
+
61
+ export function lazy(
62
+ importer: () => Promise<{ default: SyncRouteComponent }>,
63
+ ): RouteComponent {
64
+ const lazyComp = React.lazy(importer as any)
65
+ let promise: Promise<SyncRouteComponent>
66
+ let resolvedComp: SyncRouteComponent
67
+
68
+ const forwardedComp = React.forwardRef((props, ref) => {
69
+ const resolvedCompRef = React.useRef(resolvedComp || lazyComp)
70
+ return React.createElement(
71
+ resolvedCompRef.current as any,
72
+ { ...(ref ? { ref } : {}), ...props } as any,
73
+ )
74
+ })
75
+
76
+ const finalComp = forwardedComp as unknown as RouteComponent
77
+
78
+ finalComp.preload = () => {
79
+ if (!promise) {
80
+ promise = importer().then((module) => {
81
+ resolvedComp = module.default
82
+ return resolvedComp
83
+ })
84
+ }
85
+
86
+ return promise
87
+ }
88
+
89
+ return finalComp
90
+ }
91
+
92
+ type LinkPropsOptions<
93
+ TAllRouteInfo extends AnyAllRouteInfo,
94
+ TFrom extends ValidFromPath<TAllRouteInfo>,
95
+ TTo extends string,
96
+ > = LinkOptions<TAllRouteInfo, TFrom, TTo> & {
97
+ // A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
98
+ activeProps?:
99
+ | React.AnchorHTMLAttributes<HTMLAnchorElement>
100
+ | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
101
+ // A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
102
+ inactiveProps?:
103
+ | React.AnchorHTMLAttributes<HTMLAnchorElement>
104
+ | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
105
+ }
106
+
107
+ type MakeMatchRouteOptions<
108
+ TAllRouteInfo extends AnyAllRouteInfo,
109
+ TFrom extends ValidFromPath<TAllRouteInfo>,
110
+ TTo extends string,
111
+ > = ToOptions<TAllRouteInfo, TFrom, TTo> &
112
+ MatchRouteOptions & {
113
+ // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
114
+ children?:
115
+ | React.ReactNode
116
+ | ((
117
+ params: RouteInfoByPath<
118
+ TAllRouteInfo,
119
+ ResolveRelativePath<TFrom, NoInfer<TTo>>
120
+ >['allParams'],
121
+ ) => React.ReactNode)
122
+ }
123
+
124
+ type MakeLinkPropsOptions<
125
+ TAllRouteInfo extends AnyAllRouteInfo,
126
+ TFrom extends ValidFromPath<TAllRouteInfo>,
127
+ TTo extends string,
128
+ > = LinkPropsOptions<TAllRouteInfo, TFrom, TTo> &
129
+ React.AnchorHTMLAttributes<HTMLAnchorElement>
130
+
131
+ type MakeLinkOptions<
132
+ TAllRouteInfo extends AnyAllRouteInfo,
133
+ TFrom extends ValidFromPath<TAllRouteInfo>,
134
+ TTo extends string,
135
+ > = LinkPropsOptions<TAllRouteInfo, TFrom, TTo> &
136
+ React.AnchorHTMLAttributes<HTMLAnchorElement> &
137
+ Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
138
+ // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
139
+ children?:
140
+ | React.ReactNode
141
+ | ((state: { isActive: boolean }) => React.ReactNode)
142
+ }
143
+
38
144
  declare module '@tanstack/router-core' {
39
145
  interface FrameworkGenerics {
40
- Element: React.ReactNode
41
- // Any is required here so import() will work without having to do import().then(d => d.default)
42
- SyncOrAsyncElement: React.ReactNode | (() => Promise<any>)
146
+ Component: RouteComponent
43
147
  }
44
148
 
45
149
  interface Router<
@@ -50,36 +154,26 @@ declare module '@tanstack/router-core' {
50
154
  useRoute: <TId extends keyof TAllRouteInfo['routeInfoById']>(
51
155
  routeId: TId,
52
156
  ) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
53
- useMatch: <TId extends keyof TAllRouteInfo['routeInfoById']>(
157
+ useNearestMatch: () => RouteMatch<TAllRouteInfo, RouteInfo>
158
+ useMatch: <
159
+ TId extends keyof TAllRouteInfo['routeInfoById'],
160
+ TStrict extends boolean = true,
161
+ >(
54
162
  routeId: TId,
55
- ) => RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
163
+ opts?: { strict?: TStrict },
164
+ ) => TStrict extends true
165
+ ? RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
166
+ :
167
+ | RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
168
+ | undefined
56
169
  linkProps: <TTo extends string = '.'>(
57
- props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
58
- React.AnchorHTMLAttributes<HTMLAnchorElement>,
170
+ props: MakeLinkPropsOptions<TAllRouteInfo, '/', TTo>,
59
171
  ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
60
172
  Link: <TTo extends string = '.'>(
61
- props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
62
- React.AnchorHTMLAttributes<HTMLAnchorElement> &
63
- Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
64
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
65
- children?:
66
- | React.ReactNode
67
- | ((state: { isActive: boolean }) => React.ReactNode)
68
- },
173
+ props: MakeLinkOptions<TAllRouteInfo, '/', TTo>,
69
174
  ) => JSX.Element
70
175
  MatchRoute: <TTo extends string = '.'>(
71
- props: ToOptions<TAllRouteInfo, '/', TTo> &
72
- MatchRouteOptions & {
73
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
74
- children?:
75
- | React.ReactNode
76
- | ((
77
- params: RouteInfoByPath<
78
- TAllRouteInfo,
79
- ResolveRelativePath<'/', NoInfer<TTo>>
80
- >['allParams'],
81
- ) => React.ReactNode)
82
- },
176
+ props: MakeMatchRouteOptions<TAllRouteInfo, '/', TTo>,
83
177
  ) => JSX.Element
84
178
  }
85
179
 
@@ -99,53 +193,20 @@ declare module '@tanstack/router-core' {
99
193
  TResolved,
100
194
  ToIdOption<TAllRouteInfo, TRouteInfo['id'], TTo>
101
195
  >,
196
+ opts?: { strict?: boolean },
102
197
  ) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TResolved]>
103
198
  linkProps: <TTo extends string = '.'>(
104
- props: LinkPropsOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo> &
105
- React.AnchorHTMLAttributes<HTMLAnchorElement>,
199
+ props: MakeLinkPropsOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
106
200
  ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
107
201
  Link: <TTo extends string = '.'>(
108
- props: LinkPropsOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo> &
109
- React.AnchorHTMLAttributes<HTMLAnchorElement> &
110
- Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
111
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
112
- children?:
113
- | React.ReactNode
114
- | ((state: { isActive: boolean }) => React.ReactNode)
115
- },
202
+ props: MakeLinkOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
116
203
  ) => JSX.Element
117
204
  MatchRoute: <TTo extends string = '.'>(
118
- props: ToOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo> &
119
- MatchRouteOptions & {
120
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
121
- children?:
122
- | React.ReactNode
123
- | ((
124
- params: RouteInfoByPath<
125
- TAllRouteInfo,
126
- ResolveRelativePath<TRouteInfo['fullPath'], NoInfer<TTo>>
127
- >['allParams'],
128
- ) => React.ReactNode)
129
- },
205
+ props: MakeMatchRouteOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
130
206
  ) => JSX.Element
131
207
  }
132
208
  }
133
209
 
134
- type LinkPropsOptions<
135
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
136
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
137
- TTo extends string = '.',
138
- > = LinkOptions<TAllRouteInfo, TFrom, TTo> & {
139
- // A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
140
- activeProps?:
141
- | React.AnchorHTMLAttributes<HTMLAnchorElement>
142
- | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
143
- // A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
144
- inactiveProps?:
145
- | React.AnchorHTMLAttributes<HTMLAnchorElement>
146
- | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
147
- }
148
-
149
210
  export type PromptProps = {
150
211
  message: string
151
212
  when?: boolean | any
@@ -154,18 +215,18 @@ export type PromptProps = {
154
215
 
155
216
  //
156
217
 
157
- const matchesContext = React.createContext<RouteMatch[]>(null!)
158
- const routerContext = React.createContext<{ router: Router<any, any> }>(null!)
218
+ export function Link<TTo extends string = '.'>(
219
+ props: MakeLinkOptions<RegisteredAllRouteInfo, '/', TTo>,
220
+ ): JSX.Element {
221
+ const router = useRouter()
222
+ return <router.Link {...(props as any)} />
223
+ }
159
224
 
160
- // Detect if we're in the DOM
161
- const isDOM = Boolean(
162
- typeof window !== 'undefined' &&
163
- window.document &&
164
- window.document.createElement,
225
+ export const matchesContext = React.createContext<RouteMatch[]>(null!)
226
+ export const routerContext = React.createContext<{ router: RegisteredRouter }>(
227
+ null!,
165
228
  )
166
229
 
167
- const useLayoutEffect = isDOM ? React.useLayoutEffect : React.useEffect
168
-
169
230
  export type MatchesProviderProps = {
170
231
  value: RouteMatch[]
171
232
  children: React.ReactNode
@@ -237,7 +298,7 @@ export function createReactRouter<
237
298
  ...rest
238
299
  } = options
239
300
 
240
- const linkInfo = route.buildLink(options)
301
+ const linkInfo = route.buildLink(options as any)
241
302
 
242
303
  if (linkInfo.type === 'external') {
243
304
  const { href } = linkInfo
@@ -253,6 +314,12 @@ export function createReactRouter<
253
314
  next,
254
315
  } = linkInfo
255
316
 
317
+ const reactHandleClick = (e: Event) => {
318
+ React.startTransition(() => {
319
+ handleClick(e)
320
+ })
321
+ }
322
+
256
323
  const composeHandlers =
257
324
  (handlers: (undefined | ((e: any) => void))[]) =>
258
325
  (e: React.SyntheticEvent) => {
@@ -275,7 +342,7 @@ export function createReactRouter<
275
342
  ...resolvedInactiveProps,
276
343
  ...rest,
277
344
  href: disabled ? undefined : next.href,
278
- onClick: composeHandlers([handleClick, onClick]),
345
+ onClick: composeHandlers([reactHandleClick, onClick]),
279
346
  onFocus: composeHandlers([handleFocus, onFocus]),
280
347
  onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
281
348
  onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
@@ -349,7 +416,7 @@ export function createReactRouter<
349
416
  useRouterSubscription(router)
350
417
  return router.state
351
418
  },
352
- useMatch: (routeId) => {
419
+ useMatch: (routeId, opts) => {
353
420
  useRouterSubscription(router)
354
421
 
355
422
  invariant(
@@ -357,32 +424,30 @@ export function createReactRouter<
357
424
  `"${rootRouteId}" cannot be used with useMatch! Did you mean to useRoute("${rootRouteId}")?`,
358
425
  )
359
426
 
360
- const runtimeMatch = useMatch()
427
+ const runtimeMatch = useMatches()?.[0]!
361
428
  const match = router.state.matches.find((d) => d.routeId === routeId)
362
429
 
363
- invariant(
364
- match,
365
- `Could not find a match for route "${
366
- routeId as string
367
- }" being rendered in this component!`,
368
- )
369
-
370
- invariant(
371
- runtimeMatch.routeId == match?.routeId,
372
- `useMatch('${
373
- match?.routeId as string
374
- }') is being called in a component that is meant to render the '${
375
- runtimeMatch.routeId
376
- }' route. Did you mean to 'useRoute(${
377
- match?.routeId as string
378
- })' instead?`,
379
- )
380
-
381
- if (!match) {
382
- invariant('Match not found!')
430
+ if (opts?.strict ?? true) {
431
+ invariant(
432
+ match,
433
+ `Could not find an active match for "${routeId as string}"!`,
434
+ )
435
+
436
+ invariant(
437
+ runtimeMatch.routeId == match?.routeId,
438
+ `useMatch("${
439
+ match?.routeId as string
440
+ }") is being called in a component that is meant to render the '${
441
+ runtimeMatch.routeId
442
+ }' route. Did you mean to 'useMatch("${
443
+ match?.routeId as string
444
+ }", { strict: false })' or 'useRoute("${
445
+ match?.routeId as string
446
+ }")' instead?`,
447
+ )
383
448
  }
384
449
 
385
- return match
450
+ return match as any
386
451
  },
387
452
  }
388
453
 
@@ -395,19 +460,13 @@ export function createReactRouter<
395
460
 
396
461
  Object.assign(route, routeExt)
397
462
  },
398
- createElement: async (element) => {
399
- if (typeof element === 'function') {
400
- const res = (await element()) as any
401
-
402
- // Support direct import() calls
403
- if (typeof res === 'object' && res.default) {
404
- return React.createElement(res.default)
405
- } else {
406
- return res
407
- }
463
+ loadComponent: async (component) => {
464
+ if (component.preload && typeof document !== 'undefined') {
465
+ component.preload()
466
+ // return await component.preload()
408
467
  }
409
468
 
410
- return element
469
+ return component as any
411
470
  },
412
471
  })
413
472
 
@@ -430,13 +489,13 @@ export function RouterProvider<
430
489
  router.update(rest)
431
490
 
432
491
  useRouterSubscription(router)
433
-
434
- useLayoutEffect(() => {
492
+ React.useEffect(() => {
493
+ console.log('hello')
435
494
  return router.mount()
436
495
  }, [router])
437
496
 
438
497
  return (
439
- <routerContext.Provider value={{ router }}>
498
+ <routerContext.Provider value={{ router: router as any }}>
440
499
  <MatchesProvider value={router.state.matches}>
441
500
  {children ?? <Outlet />}
442
501
  </MatchesProvider>
@@ -444,93 +503,123 @@ export function RouterProvider<
444
503
  )
445
504
  }
446
505
 
447
- function useRouter(): Router {
506
+ export function useRouter(): RegisteredRouter {
448
507
  const value = React.useContext(routerContext)
449
508
  warning(!value, 'useRouter must be used inside a <Router> component!')
450
509
 
451
510
  useRouterSubscription(value.router)
452
511
 
453
- return value.router as Router
512
+ return value.router
454
513
  }
455
514
 
456
- function useMatches(): RouteMatch[] {
515
+ export function useMatches(): RouteMatch[] {
457
516
  return React.useContext(matchesContext)
458
517
  }
459
518
 
460
- // function useParentMatches(): RouteMatch[] {
461
- // const router = useRouter()
462
- // const match = useMatch()
463
- // const matches = router.state.matches
464
- // return matches.slice(
465
- // 0,
466
- // matches.findIndex((d) => d.matchId === match.matchId) - 1,
467
- // )
468
- // }
469
-
470
- function useMatch<T>(): RouteMatch {
471
- return useMatches()?.[0] as RouteMatch
519
+ export function useMatch<
520
+ TId extends keyof RegisteredAllRouteInfo['routeInfoById'],
521
+ TStrict extends boolean = true,
522
+ >(
523
+ routeId: TId,
524
+ opts?: { strict?: TStrict },
525
+ ): TStrict extends true
526
+ ? RouteMatch<
527
+ RegisteredAllRouteInfo,
528
+ RegisteredAllRouteInfo['routeInfoById'][TId]
529
+ >
530
+ :
531
+ | RouteMatch<
532
+ RegisteredAllRouteInfo,
533
+ RegisteredAllRouteInfo['routeInfoById'][TId]
534
+ >
535
+ | undefined {
536
+ const router = useRouter()
537
+ return router.useMatch(routeId as any, opts) as any
472
538
  }
473
539
 
474
- export function Outlet() {
475
- const router = useRouter()
476
- const [, ...matches] = useMatches()
540
+ export function useNearestMatch(): RouteMatch<
541
+ RegisteredAllRouteInfo,
542
+ RouteInfo
543
+ > {
544
+ const runtimeMatch = useMatches()?.[0]!
477
545
 
478
- const childMatch = matches[0]
546
+ invariant(runtimeMatch, `Could not find a nearest match!`)
479
547
 
480
- if (!childMatch) return null
548
+ return runtimeMatch as any
549
+ }
481
550
 
482
- const element = ((): React.ReactNode => {
483
- if (!childMatch) {
484
- return null
485
- }
551
+ export function useRoute<
552
+ TId extends keyof RegisteredAllRouteInfo['routeInfoById'],
553
+ >(
554
+ routeId: TId,
555
+ ): Route<RegisteredAllRouteInfo, RegisteredAllRouteInfo['routeInfoById'][TId]> {
556
+ const router = useRouter()
557
+ return router.useRoute(routeId as any) as any
558
+ }
486
559
 
487
- const errorElement =
488
- childMatch.__.errorElement ?? router.options.defaultErrorElement
560
+ export function linkProps<TTo extends string = '.'>(
561
+ props: MakeLinkPropsOptions<RegisteredAllRouteInfo, '/', TTo>,
562
+ ): React.AnchorHTMLAttributes<HTMLAnchorElement> {
563
+ const router = useRouter()
564
+ return router.linkProps(props as any)
565
+ }
489
566
 
490
- if (childMatch.status === 'error') {
491
- if (errorElement) {
492
- return errorElement as any
493
- }
567
+ export function MatchRoute<TTo extends string = '.'>(
568
+ props: MakeMatchRouteOptions<RegisteredAllRouteInfo, '/', TTo>,
569
+ ): JSX.Element {
570
+ const router = useRouter()
571
+ return React.createElement(router.MatchRoute, props as any)
572
+ }
494
573
 
495
- if (
496
- childMatch.options.useErrorBoundary ||
497
- router.options.useErrorBoundary
498
- ) {
499
- throw childMatch.error
500
- }
574
+ export function Outlet() {
575
+ const router = useRouter()
576
+ const matches = useMatches().slice(1)
577
+ const match = matches[0]
501
578
 
502
- return <DefaultErrorBoundary error={childMatch.error} />
503
- }
579
+ const defaultPending = React.useCallback(() => null, [])
504
580
 
505
- if (childMatch.status === 'loading' || childMatch.status === 'idle') {
506
- if (childMatch.isPending) {
507
- const pendingElement =
508
- childMatch.__.pendingElement ?? router.options.defaultPendingElement
581
+ if (!match) {
582
+ return null
583
+ }
509
584
 
510
- if (childMatch.options.pendingMs || pendingElement) {
511
- return (pendingElement as any) ?? null
512
- }
513
- }
585
+ const PendingComponent = (match.__.pendingComponent ??
586
+ router.options.defaultPendingComponent ??
587
+ defaultPending) as any
514
588
 
515
- return null
516
- }
589
+ const errorComponent =
590
+ match.__.errorComponent ?? router.options.defaultErrorComponent
517
591
 
518
- return (childMatch.__.element as any) ?? router.options.defaultElement
519
- })() as JSX.Element
592
+ return (
593
+ <MatchesProvider value={matches}>
594
+ <React.Suspense fallback={<PendingComponent />}>
595
+ <CatchBoundary errorComponent={errorComponent}>
596
+ {
597
+ ((): React.ReactNode => {
598
+ if (match.status === 'error') {
599
+ throw match.error
600
+ }
520
601
 
521
- const catchElement =
522
- childMatch?.options.catchElement ?? router.options.defaultCatchElement
602
+ if (match.status === 'success') {
603
+ return React.createElement(
604
+ (match.__.component as any) ??
605
+ router.options.defaultComponent ??
606
+ Outlet,
607
+ )
608
+ }
523
609
 
524
- return (
525
- <MatchesProvider value={matches} key={childMatch.matchId}>
526
- <CatchBoundary catchElement={catchElement}>{element}</CatchBoundary>
610
+ console.log(match.matchId, 'suspend')
611
+ throw match.__.loadPromise
612
+ })() as JSX.Element
613
+ }
614
+ </CatchBoundary>
615
+ </React.Suspense>
527
616
  </MatchesProvider>
528
617
  )
529
618
  }
530
619
 
531
620
  class CatchBoundary extends React.Component<{
532
621
  children: any
533
- catchElement: any
622
+ errorComponent: any
534
623
  }> {
535
624
  state = {
536
625
  error: false,
@@ -543,19 +632,11 @@ class CatchBoundary extends React.Component<{
543
632
  info,
544
633
  })
545
634
  }
546
- reset = () => {
547
- this.setState({
548
- error: false,
549
- info: false,
550
- })
551
- }
552
635
  render() {
553
- const catchElement = this.props.catchElement ?? DefaultErrorBoundary
636
+ const errorComponent = this.props.errorComponent ?? DefaultErrorBoundary
554
637
 
555
638
  if (this.state.error) {
556
- return typeof catchElement === 'function'
557
- ? catchElement(this.state)
558
- : catchElement
639
+ return React.createElement(errorComponent, this.state)
559
640
  }
560
641
 
561
642
  return this.props.children
@@ -584,19 +665,6 @@ export function DefaultErrorBoundary({ error }: { error: any }) {
584
665
  ) : null}
585
666
  </pre>
586
667
  </div>
587
- <div style={{ height: '1rem' }} />
588
- <div
589
- style={{
590
- fontSize: '.8em',
591
- borderLeft: '3px solid rgba(127, 127, 127, 1)',
592
- paddingLeft: '.5rem',
593
- opacity: 0.5,
594
- }}
595
- >
596
- If you are the owner of this website, it's highly recommended that you
597
- configure your own custom Catch/Error boundaries for the router. You can
598
- optionally configure a boundary for each route.
599
- </div>
600
668
  </div>
601
669
  )
602
670
  }