@tanstack/react-router 0.0.1-beta.61 → 0.0.1-beta.63

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/src/index.tsx CHANGED
@@ -24,6 +24,12 @@ import {
24
24
  invariant,
25
25
  Router,
26
26
  Expand,
27
+ AnyContext,
28
+ AnyRootRoute,
29
+ RootRoute,
30
+ AnySearchSchema,
31
+ AnyPathParams,
32
+ AnyRouteMatch,
27
33
  } from '@tanstack/router'
28
34
  import { useStore } from '@tanstack/react-store'
29
35
 
@@ -119,9 +125,13 @@ declare module '@tanstack/router' {
119
125
  }>
120
126
  }
121
127
 
122
- interface RouterOptions<TRouteTree, TRouterContext> {
128
+ interface RouterOptions<TRouteTree> {
123
129
  // ssrFooter?: () => JSX.Element | Node
124
130
  }
131
+
132
+ interface FrameworkRouteOptions {
133
+ wrapInSuspense?: boolean
134
+ }
125
135
  }
126
136
 
127
137
  export type PromptProps = {
@@ -138,7 +148,7 @@ export function useLinkProps<
138
148
  >(
139
149
  options: MakeLinkPropsOptions<TFrom, TTo>,
140
150
  ): React.AnchorHTMLAttributes<HTMLAnchorElement> {
141
- const router = useRouter()
151
+ const router = useRouterContext()
142
152
 
143
153
  const {
144
154
  // custom props
@@ -274,7 +284,7 @@ export const Link: LinkFn = React.forwardRef((props: any, ref) => {
274
284
  )
275
285
  }) as any
276
286
 
277
- type MatchesContextValue = RouteMatch[]
287
+ type MatchesContextValue = AnyRouteMatch[]
278
288
 
279
289
  export const matchesContext = React.createContext<MatchesContextValue>(null!)
280
290
  export const routerContext = React.createContext<{ router: RegisteredRouter }>(
@@ -287,11 +297,10 @@ export type MatchesProviderProps = {
287
297
  }
288
298
 
289
299
  export class ReactRouter<
290
- TRouteConfig extends AnyRoute = Route,
300
+ TRouteConfig extends AnyRootRoute = RootRoute,
291
301
  TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteConfig>,
292
- TRouterContext = unknown,
293
- > extends Router<TRouteConfig, TRoutesInfo, TRouterContext> {
294
- constructor(opts: RouterOptions<TRouteConfig, TRouterContext>) {
302
+ > extends Router<TRouteConfig, TRoutesInfo> {
303
+ constructor(opts: RouterOptions<TRouteConfig>) {
295
304
  super({
296
305
  ...opts,
297
306
  loadComponent: async (component) => {
@@ -306,25 +315,19 @@ export class ReactRouter<
306
315
  }
307
316
 
308
317
  export type RouterProps<
309
- TRouteConfig extends AnyRoute = Route,
318
+ TRouteConfig extends AnyRootRoute = RootRoute,
310
319
  TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,
311
- TRouterContext = unknown,
312
- > = RouterOptions<TRouteConfig, TRouterContext> & {
313
- router: Router<TRouteConfig, TRoutesInfo, TRouterContext>
320
+ > = RouterOptions<TRouteConfig> & {
321
+ router: Router<TRouteConfig, TRoutesInfo>
314
322
  }
315
323
 
316
324
  export function RouterProvider<
317
- TRouteConfig extends AnyRoute = Route,
325
+ TRouteConfig extends AnyRootRoute = RootRoute,
318
326
  TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,
319
- TRouterContext = unknown,
320
- >({ router, ...rest }: RouterProps<TRouteConfig, TRoutesInfo, TRouterContext>) {
327
+ >({ router, ...rest }: RouterProps<TRouteConfig, TRoutesInfo>) {
321
328
  router.update(rest)
322
329
 
323
- const currentMatches = useStore(
324
- router.store,
325
- (s) => s.currentMatches,
326
- undefined,
327
- )
330
+ const currentMatches = useStore(router.store, (s) => s.currentMatches)
328
331
 
329
332
  React.useEffect(router.mount, [router])
330
333
 
@@ -339,18 +342,22 @@ export function RouterProvider<
339
342
  )
340
343
  }
341
344
 
342
- export function useRouter(): RegisteredRouter {
345
+ export function useRouterContext(): RegisteredRouter {
343
346
  const value = React.useContext(routerContext)
344
347
  warning(!value, 'useRouter must be used inside a <Router> component!')
348
+
349
+ useStore(value.router.store)
350
+
345
351
  return value.router
346
352
  }
347
353
 
348
- export function useRouterStore<T = RouterStore>(
349
- selector?: (state: Router['store']) => T,
354
+ export function useRouter<T = RouterStore>(
355
+ track?: (state: Router['store']) => T,
350
356
  shallow?: boolean,
351
- ): T {
352
- const router = useRouter()
353
- return useStore(router.store, selector as any, shallow)
357
+ ): RegisteredRouter {
358
+ const router = useRouterContext()
359
+ useStore(router.store, track as any, shallow)
360
+ return router
354
361
  }
355
362
 
356
363
  export function useMatches(): RouteMatch[] {
@@ -370,10 +377,10 @@ export function useMatch<
370
377
  track?: (match: TRouteMatch) => any
371
378
  shallow?: boolean
372
379
  }): TStrict extends true ? TRouteMatch : TRouteMatch | undefined {
373
- const router = useRouter()
380
+ const router = useRouterContext()
374
381
  const nearestMatch = useMatches()[0]!
375
382
  const match = opts?.from
376
- ? router.store.state.currentMatches.find((d) => d.route.id === opts?.from)
383
+ ? router.state.currentMatches.find((d) => d.route.id === opts?.from)
377
384
  : nearestMatch
378
385
 
379
386
  invariant(
@@ -399,7 +406,7 @@ export function useMatch<
399
406
  }
400
407
 
401
408
  useStore(
402
- match!.store,
409
+ match!.store as any,
403
410
  (d) => opts?.track?.(match as any) ?? match,
404
411
  opts?.shallow,
405
412
  )
@@ -410,7 +417,7 @@ export function useMatch<
410
417
  export function useRoute<
411
418
  TId extends keyof RegisteredRoutesInfo['routesById'] = '/',
412
419
  >(routeId: TId): RegisteredRoutesInfo['routesById'][TId] {
413
- const router = useRouter()
420
+ const router = useRouterContext()
414
421
  const resolvedRoute = router.getRoute(routeId as any)
415
422
 
416
423
  invariant(
@@ -437,35 +444,38 @@ export function useSearch<
437
444
  useStore(
438
445
  (match as any).store,
439
446
  (d: any) => opts?.track?.(d.search) ?? d.search,
447
+ true,
440
448
  )
441
449
 
442
- return (match as unknown as RouteMatch).store.state.search as any
450
+ return (match as unknown as RouteMatch).state.search as any
443
451
  }
444
452
 
445
453
  export function useParams<
446
454
  TFrom extends keyof RegisteredRoutesInfo['routesById'] = '/',
447
- TDefaultSelected = Expand<
448
- RegisteredRoutesInfo['allParams'] &
449
- RegisteredRoutesInfo['routesById'][TFrom]['__types']['allParams']
450
- >,
455
+ TDefaultSelected = RegisteredRoutesInfo['allParams'] &
456
+ RegisteredRoutesInfo['routesById'][TFrom]['__types']['allParams'],
451
457
  TSelected = TDefaultSelected,
452
458
  >(opts?: {
453
459
  from: TFrom
454
460
  track?: (search: TDefaultSelected) => TSelected
455
461
  }): TSelected {
456
- const router = useRouter()
457
- useStore(router.store, (d) => {
458
- const params = last(d.currentMatches)?.params as any
459
- return opts?.track?.(params) ?? params
460
- })
462
+ const router = useRouterContext()
463
+ useStore(
464
+ router.store,
465
+ (d) => {
466
+ const params = last(d.currentMatches)?.params as any
467
+ return opts?.track?.(params) ?? params
468
+ },
469
+ true,
470
+ )
461
471
 
462
- return last(router.store.state.currentMatches)?.params as any
472
+ return last(router.state.currentMatches)?.params as any
463
473
  }
464
474
 
465
475
  export function useNavigate<
466
476
  TDefaultFrom extends keyof RegisteredRoutesInfo['routesById'] = '/',
467
477
  >(defaultOpts?: { from?: TDefaultFrom }) {
468
- const router = useRouter()
478
+ const router = useRouterContext()
469
479
  return <
470
480
  TFrom extends keyof RegisteredRoutesInfo['routesById'] = TDefaultFrom,
471
481
  TTo extends string = '.',
@@ -477,7 +487,7 @@ export function useNavigate<
477
487
  }
478
488
 
479
489
  export function useMatchRoute() {
480
- const router = useRouter()
490
+ const router = useRouterContext()
481
491
 
482
492
  return <
483
493
  TFrom extends ValidFromPath<RegisteredRoutesInfo> = '/',
@@ -530,17 +540,17 @@ function SubOutlet({
530
540
  matches: RouteMatch[]
531
541
  match: RouteMatch
532
542
  }) {
533
- const router = useRouter()
534
- useStore(match!.store)
543
+ const router = useRouterContext()
544
+ useStore(match!.store, (store) => [store.status, store.error], true)
535
545
 
536
546
  const defaultPending = React.useCallback(() => null, [])
537
547
 
538
548
  const Inner = React.useCallback((props: { match: RouteMatch }): any => {
539
- if (props.match.store.state.status === 'error') {
540
- throw props.match.store.state.error
549
+ if (props.match.state.status === 'error') {
550
+ throw props.match.state.error
541
551
  }
542
552
 
543
- if (props.match.store.state.status === 'success') {
553
+ if (props.match.state.status === 'success') {
544
554
  return React.createElement(
545
555
  (props.match.component as any) ??
546
556
  router.options.defaultComponent ??
@@ -548,7 +558,7 @@ function SubOutlet({
548
558
  )
549
559
  }
550
560
 
551
- if (props.match.store.state.status === 'pending') {
561
+ if (props.match.state.status === 'pending') {
552
562
  throw props.match.__loadPromise
553
563
  }
554
564
 
@@ -567,7 +577,17 @@ function SubOutlet({
567
577
 
568
578
  return (
569
579
  <matchesContext.Provider value={matches}>
570
- <React.Suspense fallback={<PendingComponent />}>
580
+ {match.route.options.wrapInSuspense ?? true ? (
581
+ <React.Suspense fallback={<PendingComponent />}>
582
+ <CatchBoundary
583
+ key={match.route.id}
584
+ errorComponent={errorComponent}
585
+ match={match as any}
586
+ >
587
+ <Inner match={match} />
588
+ </CatchBoundary>
589
+ </React.Suspense>
590
+ ) : (
571
591
  <CatchBoundary
572
592
  key={match.route.id}
573
593
  errorComponent={errorComponent}
@@ -575,7 +595,7 @@ function SubOutlet({
575
595
  >
576
596
  <Inner match={match} />
577
597
  </CatchBoundary>
578
- </React.Suspense>
598
+ )}
579
599
  {/* Provide a suffix suspense boundary to make sure the router is
580
600
  ready to be dehydrated on the server */}
581
601
  {/* {router.options.ssrFooter && match.id === rootRouteId ? (
@@ -634,19 +654,19 @@ function CatchBoundaryInner(props: {
634
654
  const [activeErrorState, setActiveErrorState] = React.useState(
635
655
  props.errorState,
636
656
  )
637
- const router = useRouter()
657
+ const router = useRouterContext()
638
658
  const errorComponent = props.errorComponent ?? DefaultErrorBoundary
639
659
  const prevKeyRef = React.useRef('' as any)
640
660
 
641
661
  React.useEffect(() => {
642
662
  if (activeErrorState) {
643
- if (router.store.state.currentLocation.key !== prevKeyRef.current) {
663
+ if (router.state.currentLocation.key !== prevKeyRef.current) {
644
664
  setActiveErrorState({} as any)
645
665
  }
646
666
  }
647
667
 
648
- prevKeyRef.current = router.store.state.currentLocation.key
649
- }, [activeErrorState, router.store.state.currentLocation.key])
668
+ prevKeyRef.current = router.state.currentLocation.key
669
+ }, [activeErrorState, router.state.currentLocation.key])
650
670
 
651
671
  React.useEffect(() => {
652
672
  if (props.errorState.error) {