@depup/tanstack__react-router 1.167.5-depup.0 → 1.168.2-depup.0
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/README.md +3 -4
- package/changes.json +2 -6
- package/dist/cjs/Match.cjs +147 -58
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +22 -24
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Scripts.cjs +36 -32
- package/dist/cjs/Scripts.cjs.map +1 -1
- package/dist/cjs/Transitioner.cjs +10 -16
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/fileRoute.cjs +4 -6
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/headContentUtils.cjs +147 -59
- package/dist/cjs/headContentUtils.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.dev.cjs +1 -1
- package/dist/cjs/link.cjs +34 -29
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/not-found.cjs +20 -2
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/renderRouteNotFound.cjs +3 -3
- package/dist/cjs/renderRouteNotFound.cjs.map +1 -1
- package/dist/cjs/route.cjs +0 -2
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +2 -1
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/routerStores.cjs +21 -0
- package/dist/cjs/routerStores.cjs.map +1 -0
- package/dist/cjs/routerStores.d.cts +7 -0
- package/dist/cjs/ssr/RouterClient.cjs +1 -1
- package/dist/cjs/ssr/RouterClient.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToStream.cjs +2 -2
- package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -1
- package/dist/cjs/useCanGoBack.cjs +7 -2
- package/dist/cjs/useCanGoBack.cjs.map +1 -1
- package/dist/cjs/useLocation.cjs +21 -2
- package/dist/cjs/useLocation.cjs.map +1 -1
- package/dist/cjs/useMatch.cjs +35 -11
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/useRouter.cjs +3 -3
- package/dist/cjs/useRouter.cjs.map +1 -1
- package/dist/cjs/useRouterState.cjs +2 -2
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/esm/Match.js +148 -57
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +23 -24
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/Scripts.js +36 -32
- package/dist/esm/Scripts.js.map +1 -1
- package/dist/esm/Transitioner.js +10 -16
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/fileRoute.js +4 -4
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/headContentUtils.js +148 -60
- package/dist/esm/headContentUtils.js.map +1 -1
- package/dist/esm/index.dev.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/link.js +34 -29
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/not-found.js +20 -2
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/renderRouteNotFound.js +3 -2
- package/dist/esm/renderRouteNotFound.js.map +1 -1
- package/dist/esm/route.js +0 -2
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.js +2 -1
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/routerStores.d.ts +7 -0
- package/dist/esm/routerStores.js +20 -0
- package/dist/esm/routerStores.js.map +1 -0
- package/dist/esm/ssr/RouterClient.js +1 -1
- package/dist/esm/ssr/RouterClient.js.map +1 -1
- package/dist/esm/ssr/renderRouterToStream.js +2 -2
- package/dist/esm/ssr/renderRouterToStream.js.map +1 -1
- package/dist/esm/ssr/renderRouterToString.js +1 -1
- package/dist/esm/ssr/renderRouterToString.js.map +1 -1
- package/dist/esm/useCanGoBack.js +6 -2
- package/dist/esm/useCanGoBack.js.map +1 -1
- package/dist/esm/useLocation.js +20 -2
- package/dist/esm/useLocation.js.map +1 -1
- package/dist/esm/useMatch.js +35 -10
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useRouter.js +3 -2
- package/dist/esm/useRouter.js.map +1 -1
- package/dist/esm/useRouterState.js +2 -2
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/llms/rules/api.d.ts +1 -1
- package/dist/llms/rules/api.js +13 -19
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +27 -6
- package/package.json +5 -11
- package/src/Match.tsx +274 -81
- package/src/Matches.tsx +48 -30
- package/src/Scripts.tsx +72 -44
- package/src/Transitioner.tsx +24 -16
- package/src/fileRoute.ts +7 -9
- package/src/headContentUtils.tsx +210 -27
- package/src/link.tsx +66 -71
- package/src/not-found.tsx +41 -4
- package/src/renderRouteNotFound.tsx +6 -6
- package/src/route.tsx +0 -2
- package/src/router.ts +2 -1
- package/src/routerStores.ts +26 -0
- package/src/ssr/RouterClient.tsx +1 -1
- package/src/ssr/renderRouterToStream.tsx +2 -2
- package/src/ssr/renderRouterToString.tsx +1 -1
- package/src/useCanGoBack.ts +14 -2
- package/src/useLocation.tsx +32 -5
- package/src/useMatch.tsx +68 -19
- package/src/useRouter.tsx +7 -5
- package/src/useRouterState.tsx +4 -2
package/src/link.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
+
import { useStore } from '@tanstack/react-store'
|
|
2
3
|
import { flushSync } from 'react-dom'
|
|
3
4
|
import {
|
|
4
5
|
deepEqual,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
removeTrailingSlash,
|
|
10
11
|
} from '@tanstack/router-core'
|
|
11
12
|
import { isServer } from '@tanstack/router-core/isServer'
|
|
12
|
-
import { useRouterState } from './useRouterState'
|
|
13
13
|
import { useRouter } from './useRouter'
|
|
14
14
|
|
|
15
15
|
import { useForwardedRef, useIntersectionObserver } from './utils'
|
|
@@ -102,7 +102,7 @@ export function useLinkProps<
|
|
|
102
102
|
//
|
|
103
103
|
// For SSR parity (to avoid hydration errors), we still compute the link's
|
|
104
104
|
// active status on the server, but we avoid creating any router-state
|
|
105
|
-
// subscriptions by reading from
|
|
105
|
+
// subscriptions by reading from the location store directly.
|
|
106
106
|
//
|
|
107
107
|
// Note: `location.hash` is not available on the server.
|
|
108
108
|
// ==========================================================================
|
|
@@ -204,7 +204,7 @@ export function useLinkProps<
|
|
|
204
204
|
const isActive = (() => {
|
|
205
205
|
if (externalLink) return false
|
|
206
206
|
|
|
207
|
-
const currentLocation = router.
|
|
207
|
+
const currentLocation = router.stores.location.state
|
|
208
208
|
|
|
209
209
|
const exact = activeOptions?.exact ?? false
|
|
210
210
|
|
|
@@ -377,32 +377,13 @@ export function useLinkProps<
|
|
|
377
377
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
378
378
|
const isHydrated = useHydrated()
|
|
379
379
|
|
|
380
|
-
// subscribe to path/search/hash/params to re-build location when they change
|
|
381
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
382
|
-
const currentLocationState = useRouterState({
|
|
383
|
-
select: (s) => {
|
|
384
|
-
const leaf = s.matches[s.matches.length - 1]
|
|
385
|
-
return {
|
|
386
|
-
search: leaf?.search,
|
|
387
|
-
hash: s.location.hash,
|
|
388
|
-
path: leaf?.pathname, // path + params
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
structuralSharing: true as any,
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
const from = options.from
|
|
395
|
-
|
|
396
380
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
397
381
|
const _options = React.useMemo(
|
|
398
|
-
() =>
|
|
399
|
-
return { ...options, from }
|
|
400
|
-
},
|
|
382
|
+
() => options,
|
|
401
383
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
402
384
|
[
|
|
403
385
|
router,
|
|
404
|
-
|
|
405
|
-
from,
|
|
386
|
+
options.from,
|
|
406
387
|
options._fromLocation,
|
|
407
388
|
options.hash,
|
|
408
389
|
options.to,
|
|
@@ -415,11 +396,18 @@ export function useLinkProps<
|
|
|
415
396
|
)
|
|
416
397
|
|
|
417
398
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
399
|
+
const currentLocation = useStore(
|
|
400
|
+
router.stores.location,
|
|
401
|
+
(l) => l,
|
|
402
|
+
(prev, next) => prev.href === next.href,
|
|
421
403
|
)
|
|
422
404
|
|
|
405
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
406
|
+
const next = React.useMemo(() => {
|
|
407
|
+
const opts = { _fromLocation: currentLocation, ..._options }
|
|
408
|
+
return router.buildLocation(opts as any)
|
|
409
|
+
}, [router, currentLocation, _options])
|
|
410
|
+
|
|
423
411
|
// Use publicHref - it contains the correct href for display
|
|
424
412
|
// When a rewrite changes the origin, publicHref is the full URL
|
|
425
413
|
// Otherwise it's the origin-stripped path
|
|
@@ -474,54 +462,61 @@ export function useLinkProps<
|
|
|
474
462
|
}, [to, hrefOption, router.protocolAllowlist])
|
|
475
463
|
|
|
476
464
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
477
|
-
const isActive =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
return false
|
|
488
|
-
}
|
|
489
|
-
} else {
|
|
490
|
-
const currentPathSplit = removeTrailingSlash(
|
|
491
|
-
s.location.pathname,
|
|
492
|
-
router.basepath,
|
|
493
|
-
)
|
|
494
|
-
const nextPathSplit = removeTrailingSlash(
|
|
495
|
-
next.pathname,
|
|
496
|
-
router.basepath,
|
|
497
|
-
)
|
|
498
|
-
|
|
499
|
-
const pathIsFuzzyEqual =
|
|
500
|
-
currentPathSplit.startsWith(nextPathSplit) &&
|
|
501
|
-
(currentPathSplit.length === nextPathSplit.length ||
|
|
502
|
-
currentPathSplit[nextPathSplit.length] === '/')
|
|
503
|
-
|
|
504
|
-
if (!pathIsFuzzyEqual) {
|
|
505
|
-
return false
|
|
506
|
-
}
|
|
465
|
+
const isActive = React.useMemo(() => {
|
|
466
|
+
if (externalLink) return false
|
|
467
|
+
if (activeOptions?.exact) {
|
|
468
|
+
const testExact = exactPathTest(
|
|
469
|
+
currentLocation.pathname,
|
|
470
|
+
next.pathname,
|
|
471
|
+
router.basepath,
|
|
472
|
+
)
|
|
473
|
+
if (!testExact) {
|
|
474
|
+
return false
|
|
507
475
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
476
|
+
} else {
|
|
477
|
+
const currentPathSplit = removeTrailingSlash(
|
|
478
|
+
currentLocation.pathname,
|
|
479
|
+
router.basepath,
|
|
480
|
+
)
|
|
481
|
+
const nextPathSplit = removeTrailingSlash(next.pathname, router.basepath)
|
|
482
|
+
|
|
483
|
+
const pathIsFuzzyEqual =
|
|
484
|
+
currentPathSplit.startsWith(nextPathSplit) &&
|
|
485
|
+
(currentPathSplit.length === nextPathSplit.length ||
|
|
486
|
+
currentPathSplit[nextPathSplit.length] === '/')
|
|
487
|
+
|
|
488
|
+
if (!pathIsFuzzyEqual) {
|
|
489
|
+
return false
|
|
517
490
|
}
|
|
491
|
+
}
|
|
518
492
|
|
|
519
|
-
|
|
520
|
-
|
|
493
|
+
if (activeOptions?.includeSearch ?? true) {
|
|
494
|
+
const searchTest = deepEqual(currentLocation.search, next.search, {
|
|
495
|
+
partial: !activeOptions?.exact,
|
|
496
|
+
ignoreUndefined: !activeOptions?.explicitUndefined,
|
|
497
|
+
})
|
|
498
|
+
if (!searchTest) {
|
|
499
|
+
return false
|
|
521
500
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (activeOptions?.includeHash) {
|
|
504
|
+
return isHydrated && currentLocation.hash === next.hash
|
|
505
|
+
}
|
|
506
|
+
return true
|
|
507
|
+
}, [
|
|
508
|
+
activeOptions?.exact,
|
|
509
|
+
activeOptions?.explicitUndefined,
|
|
510
|
+
activeOptions?.includeHash,
|
|
511
|
+
activeOptions?.includeSearch,
|
|
512
|
+
currentLocation,
|
|
513
|
+
externalLink,
|
|
514
|
+
isHydrated,
|
|
515
|
+
next.hash,
|
|
516
|
+
next.pathname,
|
|
517
|
+
next.search,
|
|
518
|
+
router.basepath,
|
|
519
|
+
])
|
|
525
520
|
|
|
526
521
|
// Get the active props
|
|
527
522
|
const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive
|
package/src/not-found.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { isNotFound } from '@tanstack/router-core'
|
|
3
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
4
|
+
import { useStore } from '@tanstack/react-store'
|
|
3
5
|
import { CatchBoundary } from './CatchBoundary'
|
|
4
|
-
import {
|
|
6
|
+
import { useRouter } from './useRouter'
|
|
5
7
|
import type { ErrorInfo } from 'react'
|
|
6
8
|
import type { NotFoundError } from '@tanstack/router-core'
|
|
7
9
|
|
|
@@ -10,10 +12,45 @@ export function CatchNotFound(props: {
|
|
|
10
12
|
onCatch?: (error: Error, errorInfo: ErrorInfo) => void
|
|
11
13
|
children: React.ReactNode
|
|
12
14
|
}) {
|
|
15
|
+
const router = useRouter()
|
|
16
|
+
|
|
17
|
+
if (isServer ?? router.isServer) {
|
|
18
|
+
const pathname = router.stores.location.state.pathname
|
|
19
|
+
const status = router.stores.status.state
|
|
20
|
+
const resetKey = `not-found-${pathname}-${status}`
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<CatchBoundary
|
|
24
|
+
getResetKey={() => resetKey}
|
|
25
|
+
onCatch={(error, errorInfo) => {
|
|
26
|
+
if (isNotFound(error)) {
|
|
27
|
+
props.onCatch?.(error, errorInfo)
|
|
28
|
+
} else {
|
|
29
|
+
throw error
|
|
30
|
+
}
|
|
31
|
+
}}
|
|
32
|
+
errorComponent={({ error }) => {
|
|
33
|
+
if (isNotFound(error)) {
|
|
34
|
+
return props.fallback?.(error)
|
|
35
|
+
} else {
|
|
36
|
+
throw error
|
|
37
|
+
}
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
{props.children}
|
|
41
|
+
</CatchBoundary>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
13
45
|
// TODO: Some way for the user to programmatically reset the not-found boundary?
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
46
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
47
|
+
const pathname = useStore(
|
|
48
|
+
router.stores.location,
|
|
49
|
+
(location) => location.pathname,
|
|
50
|
+
)
|
|
51
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
52
|
+
const status = useStore(router.stores.status, (status) => status)
|
|
53
|
+
const resetKey = `not-found-${pathname}-${status}`
|
|
17
54
|
|
|
18
55
|
return (
|
|
19
56
|
<CatchBoundary
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import warning from 'tiny-warning'
|
|
3
2
|
import { DefaultGlobalNotFound } from './not-found'
|
|
4
3
|
import type { AnyRoute, AnyRouter } from '@tanstack/router-core'
|
|
5
4
|
|
|
@@ -21,11 +20,12 @@ export function renderRouteNotFound(
|
|
|
21
20
|
return <router.options.defaultNotFoundComponent {...data} />
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
if (process.env.NODE_ENV
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
24
|
+
if (!route.options.notFoundComponent) {
|
|
25
|
+
console.warn(
|
|
26
|
+
`Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<p>Not Found</p>)`,
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
return <DefaultGlobalNotFound />
|
package/src/route.tsx
CHANGED
|
@@ -258,7 +258,6 @@ export class Route<
|
|
|
258
258
|
>,
|
|
259
259
|
) {
|
|
260
260
|
super(options)
|
|
261
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
262
261
|
}
|
|
263
262
|
|
|
264
263
|
useMatch: UseMatchRoute<TId> = (opts) => {
|
|
@@ -530,7 +529,6 @@ export class RootRoute<
|
|
|
530
529
|
>,
|
|
531
530
|
) {
|
|
532
531
|
super(options)
|
|
533
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
534
532
|
}
|
|
535
533
|
|
|
536
534
|
useMatch: UseMatchRoute<RootRouteId> = (opts) => {
|
package/src/router.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RouterCore } from '@tanstack/router-core'
|
|
2
2
|
import { createFileRoute, createLazyFileRoute } from './fileRoute'
|
|
3
|
+
import { getStoreFactory } from './routerStores'
|
|
3
4
|
import type { RouterHistory } from '@tanstack/history'
|
|
4
5
|
import type {
|
|
5
6
|
AnyRoute,
|
|
@@ -114,7 +115,7 @@ export class Router<
|
|
|
114
115
|
TDehydrated
|
|
115
116
|
>,
|
|
116
117
|
) {
|
|
117
|
-
super(options)
|
|
118
|
+
super(options, getStoreFactory)
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { batch, createStore } from '@tanstack/react-store'
|
|
2
|
+
import {
|
|
3
|
+
createNonReactiveMutableStore,
|
|
4
|
+
createNonReactiveReadonlyStore,
|
|
5
|
+
} from '@tanstack/router-core'
|
|
6
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
7
|
+
import type { Readable } from '@tanstack/react-store'
|
|
8
|
+
import type { GetStoreConfig } from '@tanstack/router-core'
|
|
9
|
+
|
|
10
|
+
declare module '@tanstack/router-core' {
|
|
11
|
+
export interface RouterReadableStore<TValue> extends Readable<TValue> {}
|
|
12
|
+
}
|
|
13
|
+
export const getStoreFactory: GetStoreConfig = (opts) => {
|
|
14
|
+
if (isServer ?? opts.isServer) {
|
|
15
|
+
return {
|
|
16
|
+
createMutableStore: createNonReactiveMutableStore,
|
|
17
|
+
createReadonlyStore: createNonReactiveReadonlyStore,
|
|
18
|
+
batch: (fn) => fn(),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
createMutableStore: createStore,
|
|
23
|
+
createReadonlyStore: createStore,
|
|
24
|
+
batch: batch,
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/ssr/RouterClient.tsx
CHANGED
|
@@ -7,7 +7,7 @@ let hydrationPromise: Promise<void | Array<Array<void>>> | undefined
|
|
|
7
7
|
|
|
8
8
|
export function RouterClient(props: { router: AnyRouter }) {
|
|
9
9
|
if (!hydrationPromise) {
|
|
10
|
-
if (!props.router.state.
|
|
10
|
+
if (!props.router.stores.matchesId.state.length) {
|
|
11
11
|
hydrationPromise = hydrate(props.router)
|
|
12
12
|
} else {
|
|
13
13
|
hydrationPromise = Promise.resolve()
|
|
@@ -36,7 +36,7 @@ export const renderRouterToStream = async ({
|
|
|
36
36
|
stream as unknown as ReadableStream,
|
|
37
37
|
)
|
|
38
38
|
return new Response(responseStream as any, {
|
|
39
|
-
status: router.
|
|
39
|
+
status: router.stores.statusCode.state,
|
|
40
40
|
headers: responseHeaders,
|
|
41
41
|
})
|
|
42
42
|
}
|
|
@@ -79,7 +79,7 @@ export const renderRouterToStream = async ({
|
|
|
79
79
|
reactAppPassthrough,
|
|
80
80
|
)
|
|
81
81
|
return new Response(responseStream as any, {
|
|
82
|
-
status: router.
|
|
82
|
+
status: router.stores.statusCode.state,
|
|
83
83
|
headers: responseHeaders,
|
|
84
84
|
})
|
|
85
85
|
}
|
package/src/useCanGoBack.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useStore } from '@tanstack/react-store'
|
|
2
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
3
|
+
import { useRouter } from './useRouter'
|
|
2
4
|
|
|
3
5
|
export function useCanGoBack() {
|
|
4
|
-
|
|
6
|
+
const router = useRouter()
|
|
7
|
+
|
|
8
|
+
if (isServer ?? router.isServer) {
|
|
9
|
+
return router.stores.location.state.state.__TSR_index !== 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
13
|
+
return useStore(
|
|
14
|
+
router.stores.location,
|
|
15
|
+
(location) => location.state.__TSR_index !== 0,
|
|
16
|
+
)
|
|
5
17
|
}
|
package/src/useLocation.tsx
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useStore } from '@tanstack/react-store'
|
|
2
|
+
import { useRef } from 'react'
|
|
3
|
+
import { replaceEqualDeep } from '@tanstack/router-core'
|
|
4
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
5
|
+
import { useRouter } from './useRouter'
|
|
2
6
|
import type {
|
|
3
7
|
StructuralSharingOption,
|
|
4
8
|
ValidateSelected,
|
|
@@ -45,8 +49,31 @@ export function useLocation<
|
|
|
45
49
|
opts?: UseLocationBaseOptions<TRouter, TSelected, TStructuralSharing> &
|
|
46
50
|
StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,
|
|
47
51
|
): UseLocationResult<TRouter, TSelected> {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
const router = useRouter<TRouter>()
|
|
53
|
+
|
|
54
|
+
if (isServer ?? router.isServer) {
|
|
55
|
+
const location = router.stores.location.state
|
|
56
|
+
return (
|
|
57
|
+
opts?.select ? opts.select(location as any) : location
|
|
58
|
+
) as UseLocationResult<TRouter, TSelected>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const previousResult =
|
|
62
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
63
|
+
useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(undefined)
|
|
64
|
+
|
|
65
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
66
|
+
return useStore(router.stores.location, (location) => {
|
|
67
|
+
const selected = (
|
|
68
|
+
opts?.select ? opts.select(location as any) : location
|
|
69
|
+
) as ValidateSelected<TRouter, TSelected, TStructuralSharing>
|
|
70
|
+
|
|
71
|
+
if (opts?.structuralSharing ?? router.options.defaultStructuralSharing) {
|
|
72
|
+
const shared = replaceEqualDeep(previousResult.current, selected)
|
|
73
|
+
previousResult.current = shared
|
|
74
|
+
return shared
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return selected
|
|
78
|
+
}) as UseLocationResult<TRouter, TSelected>
|
|
52
79
|
}
|
package/src/useMatch.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { useStore } from '@tanstack/react-store'
|
|
3
|
+
import { invariant, replaceEqualDeep } from '@tanstack/router-core'
|
|
4
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
4
5
|
import { dummyMatchContext, matchContext } from './matchContext'
|
|
6
|
+
import { useRouter } from './useRouter'
|
|
5
7
|
import type {
|
|
6
8
|
StructuralSharingOption,
|
|
7
9
|
ValidateSelected,
|
|
@@ -16,6 +18,12 @@ import type {
|
|
|
16
18
|
ThrowOrOptional,
|
|
17
19
|
} from '@tanstack/router-core'
|
|
18
20
|
|
|
21
|
+
const dummyStore = {
|
|
22
|
+
state: undefined,
|
|
23
|
+
get: () => undefined,
|
|
24
|
+
subscribe: () => () => {},
|
|
25
|
+
} as any
|
|
26
|
+
|
|
19
27
|
export interface UseMatchBaseOptions<
|
|
20
28
|
TRouter extends AnyRouter,
|
|
21
29
|
TFrom,
|
|
@@ -96,28 +104,69 @@ export function useMatch<
|
|
|
96
104
|
TStructuralSharing
|
|
97
105
|
>,
|
|
98
106
|
): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {
|
|
107
|
+
const router = useRouter<TRouter>()
|
|
99
108
|
const nearestMatchId = React.useContext(
|
|
100
109
|
opts.from ? dummyMatchContext : matchContext,
|
|
101
110
|
)
|
|
102
111
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
|
|
112
|
+
const key = opts.from ?? nearestMatchId
|
|
113
|
+
const matchStore = key
|
|
114
|
+
? opts.from
|
|
115
|
+
? router.stores.getMatchStoreByRouteId(key)
|
|
116
|
+
: router.stores.activeMatchStoresById.get(key)
|
|
117
|
+
: undefined
|
|
118
|
+
|
|
119
|
+
if (isServer ?? router.isServer) {
|
|
120
|
+
const match = matchStore?.state
|
|
121
|
+
if ((opts.shouldThrow ?? true) && !match) {
|
|
122
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
125
|
+
)
|
|
115
126
|
}
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
invariant()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (match === undefined) {
|
|
132
|
+
return undefined as any
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return (opts.select ? opts.select(match as any) : match) as any
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const previousResult =
|
|
139
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
140
|
+
React.useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(
|
|
141
|
+
undefined,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
145
|
+
return useStore(matchStore ?? dummyStore, (match) => {
|
|
146
|
+
if ((opts.shouldThrow ?? true) && !match) {
|
|
147
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
invariant()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (match === undefined) {
|
|
157
|
+
return undefined
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const selected = (
|
|
161
|
+
opts.select ? opts.select(match as any) : match
|
|
162
|
+
) as ValidateSelected<TRouter, TSelected, TStructuralSharing>
|
|
163
|
+
|
|
164
|
+
if (opts.structuralSharing ?? router.options.defaultStructuralSharing) {
|
|
165
|
+
const shared = replaceEqualDeep(previousResult.current, selected)
|
|
166
|
+
previousResult.current = shared
|
|
167
|
+
return shared
|
|
168
|
+
}
|
|
121
169
|
|
|
122
|
-
|
|
170
|
+
return selected
|
|
171
|
+
}) as any
|
|
123
172
|
}
|
package/src/useRouter.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import warning from 'tiny-warning'
|
|
3
2
|
import { routerContext } from './routerContext'
|
|
4
3
|
import type { AnyRouter, RegisteredRouter } from '@tanstack/router-core'
|
|
5
4
|
|
|
@@ -17,9 +16,12 @@ export function useRouter<TRouter extends AnyRouter = RegisteredRouter>(opts?: {
|
|
|
17
16
|
warn?: boolean
|
|
18
17
|
}): TRouter {
|
|
19
18
|
const value = React.useContext(routerContext)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
20
|
+
if ((opts?.warn ?? true) && !value) {
|
|
21
|
+
console.warn(
|
|
22
|
+
'Warning: useRouter must be used inside a <RouterProvider> component!',
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
24
26
|
return value as any
|
|
25
27
|
}
|
package/src/useRouterState.tsx
CHANGED
|
@@ -57,7 +57,9 @@ export function useRouterState<
|
|
|
57
57
|
// Avoid subscribing to the store (and any structural sharing work) on the server.
|
|
58
58
|
const _isServer = isServer ?? router.isServer
|
|
59
59
|
if (_isServer) {
|
|
60
|
-
const state = router.state as RouterState<
|
|
60
|
+
const state = router.stores.__store.state as RouterState<
|
|
61
|
+
TRouter['routeTree']
|
|
62
|
+
>
|
|
61
63
|
return (opts?.select ? opts.select(state) : state) as UseRouterStateResult<
|
|
62
64
|
TRouter,
|
|
63
65
|
TSelected
|
|
@@ -69,7 +71,7 @@ export function useRouterState<
|
|
|
69
71
|
useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(undefined)
|
|
70
72
|
|
|
71
73
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
72
|
-
return useStore(router.__store, (state) => {
|
|
74
|
+
return useStore(router.stores.__store, (state) => {
|
|
73
75
|
if (opts?.select) {
|
|
74
76
|
if (opts.structuralSharing ?? router.options.defaultStructuralSharing) {
|
|
75
77
|
const newSlice = replaceEqualDeep(
|