@tanstack/react-router 0.0.1-beta.60 → 0.0.1-beta.62
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/build/cjs/index.js +37 -29
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +37 -29
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +52 -52
- package/build/types/index.d.ts +16 -13
- package/build/umd/index.development.js +179 -163
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +3 -3
- package/build/umd/index.production.js.map +1 -1
- package/package.json +3 -3
- package/src/index.tsx +74 -54
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
|
|
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 =
|
|
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 =
|
|
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
|
|
300
|
+
TRouteConfig extends AnyRootRoute = RootRoute,
|
|
291
301
|
TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteConfig>,
|
|
292
|
-
|
|
293
|
-
|
|
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
|
|
318
|
+
TRouteConfig extends AnyRootRoute = RootRoute,
|
|
310
319
|
TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,
|
|
311
|
-
|
|
312
|
-
|
|
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
|
|
325
|
+
TRouteConfig extends AnyRootRoute = RootRoute,
|
|
318
326
|
TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,
|
|
319
|
-
|
|
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
|
|
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
|
|
349
|
-
|
|
354
|
+
export function useRouter<T = RouterStore>(
|
|
355
|
+
track?: (state: Router['store']) => T,
|
|
350
356
|
shallow?: boolean,
|
|
351
|
-
):
|
|
352
|
-
const router =
|
|
353
|
-
|
|
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 =
|
|
380
|
+
const router = useRouterContext()
|
|
374
381
|
const nearestMatch = useMatches()[0]!
|
|
375
382
|
const match = opts?.from
|
|
376
|
-
? router.
|
|
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 =
|
|
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).
|
|
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 =
|
|
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 =
|
|
457
|
-
useStore(
|
|
458
|
-
|
|
459
|
-
|
|
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.
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
540
|
-
throw props.match.
|
|
549
|
+
if (props.match.state.status === 'error') {
|
|
550
|
+
throw props.match.state.error
|
|
541
551
|
}
|
|
542
552
|
|
|
543
|
-
if (props.match.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
663
|
+
if (router.state.currentLocation.key !== prevKeyRef.current) {
|
|
644
664
|
setActiveErrorState({} as any)
|
|
645
665
|
}
|
|
646
666
|
}
|
|
647
667
|
|
|
648
|
-
prevKeyRef.current = router.
|
|
649
|
-
}, [activeErrorState, router.
|
|
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) {
|