@tanstack/vue-router 1.167.4 → 1.168.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/dist/esm/Match.js +55 -61
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +8 -15
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/Scripts.js +7 -6
- package/dist/esm/Scripts.js.map +1 -1
- package/dist/esm/Transitioner.js +18 -24
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/headContentUtils.js +13 -15
- package/dist/esm/headContentUtils.js.map +1 -1
- package/dist/esm/index.dev.js +6 -6
- package/dist/esm/index.js +6 -6
- package/dist/esm/link.js +242 -178
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/matchContext.d.ts +8 -14
- package/dist/esm/matchContext.js +11 -9
- package/dist/esm/matchContext.js.map +1 -1
- package/dist/esm/not-found.js +6 -3
- package/dist/esm/not-found.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 +13 -0
- package/dist/esm/routerStores.js +33 -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.d.ts +1 -1
- package/dist/esm/useCanGoBack.js +3 -2
- package/dist/esm/useCanGoBack.js.map +1 -1
- package/dist/esm/useLocation.js +3 -2
- package/dist/esm/useLocation.js.map +1 -1
- package/dist/esm/useMatch.js +29 -19
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useRouterState.js +4 -4
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/source/Match.jsx +121 -159
- package/dist/source/Match.jsx.map +1 -1
- package/dist/source/Matches.jsx +11 -28
- package/dist/source/Matches.jsx.map +1 -1
- package/dist/source/Scripts.jsx +32 -35
- package/dist/source/Scripts.jsx.map +1 -1
- package/dist/source/Transitioner.jsx +19 -21
- package/dist/source/Transitioner.jsx.map +1 -1
- package/dist/source/headContentUtils.jsx +51 -61
- package/dist/source/headContentUtils.jsx.map +1 -1
- package/dist/source/link.jsx +298 -249
- package/dist/source/link.jsx.map +1 -1
- package/dist/source/matchContext.d.ts +8 -14
- package/dist/source/matchContext.jsx +17 -23
- package/dist/source/matchContext.jsx.map +1 -1
- package/dist/source/not-found.jsx +6 -5
- package/dist/source/not-found.jsx.map +1 -1
- package/dist/source/router.js +2 -1
- package/dist/source/router.js.map +1 -1
- package/dist/source/routerStores.d.ts +13 -0
- package/dist/source/routerStores.js +37 -0
- package/dist/source/routerStores.js.map +1 -0
- package/dist/source/ssr/RouterClient.jsx +1 -1
- package/dist/source/ssr/RouterClient.jsx.map +1 -1
- package/dist/source/ssr/renderRouterToStream.jsx +2 -2
- package/dist/source/ssr/renderRouterToStream.jsx.map +1 -1
- package/dist/source/ssr/renderRouterToString.jsx +1 -1
- package/dist/source/ssr/renderRouterToString.jsx.map +1 -1
- package/dist/source/useCanGoBack.d.ts +1 -1
- package/dist/source/useCanGoBack.js +4 -2
- package/dist/source/useCanGoBack.js.map +1 -1
- package/dist/source/useLocation.jsx +4 -4
- package/dist/source/useLocation.jsx.map +1 -1
- package/dist/source/useMatch.jsx +60 -38
- package/dist/source/useMatch.jsx.map +1 -1
- package/dist/source/useRouterState.jsx +4 -4
- package/dist/source/useRouterState.jsx.map +1 -1
- package/package.json +2 -2
- package/skills/vue-router/SKILL.md +3 -0
- package/src/Match.tsx +168 -180
- package/src/Matches.tsx +18 -31
- package/src/Scripts.tsx +40 -40
- package/src/Transitioner.tsx +35 -23
- package/src/headContentUtils.tsx +101 -107
- package/src/link.tsx +445 -300
- package/src/matchContext.tsx +23 -25
- package/src/not-found.tsx +9 -5
- package/src/router.ts +2 -1
- package/src/routerStores.ts +54 -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 +7 -2
- package/src/useLocation.tsx +8 -5
- package/src/useMatch.tsx +95 -49
- package/src/useRouterState.tsx +6 -4
package/src/matchContext.tsx
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
import * as Vue from 'vue'
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// Reactive nearest-match context used by hooks that work relative to the
|
|
4
|
+
// current match in the tree.
|
|
5
5
|
export const matchContext = Symbol('TanStackRouterMatch') as Vue.InjectionKey<
|
|
6
6
|
Vue.Ref<string | undefined>
|
|
7
7
|
>
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
export const
|
|
11
|
-
'
|
|
12
|
-
) as Vue.InjectionKey<Vue.Ref<
|
|
9
|
+
// Pending match context for nearest-match lookups
|
|
10
|
+
export const pendingMatchContext = Symbol(
|
|
11
|
+
'TanStackRouterPendingMatch',
|
|
12
|
+
) as Vue.InjectionKey<Vue.Ref<boolean>>
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Vue.provide(matchContext, Vue.ref(matchId))
|
|
19
|
-
}
|
|
14
|
+
// Dummy pending context when nearest pending state is not needed
|
|
15
|
+
export const dummyPendingMatchContext = Symbol(
|
|
16
|
+
'TanStackRouterDummyPendingMatch',
|
|
17
|
+
) as Vue.InjectionKey<Vue.Ref<boolean>>
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
// Stable routeId context — a plain string (not reactive) that identifies
|
|
20
|
+
// which route this component belongs to. Provided by Match, consumed by
|
|
21
|
+
// MatchInner, Outlet, and useMatch for routeId-based store lookups.
|
|
22
|
+
export const routeIdContext = Symbol(
|
|
23
|
+
'TanStackRouterRouteId',
|
|
24
|
+
) as Vue.InjectionKey<string>
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
|
-
*
|
|
27
|
+
* Retrieves nearest pending-match state from the component tree
|
|
30
28
|
*/
|
|
31
|
-
export function
|
|
32
|
-
Vue.
|
|
29
|
+
export function injectPendingMatch(): Vue.Ref<boolean> {
|
|
30
|
+
return Vue.inject(pendingMatchContext, Vue.ref(false))
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
|
-
* Retrieves
|
|
37
|
-
* This only exists so we can conditionally inject a value when we are not interested in the nearest match
|
|
34
|
+
* Retrieves dummy pending-match state from the component tree
|
|
35
|
+
* This only exists so we can conditionally inject a value when we are not interested in the nearest pending match
|
|
38
36
|
*/
|
|
39
|
-
export function
|
|
40
|
-
return Vue.inject(
|
|
37
|
+
export function injectDummyPendingMatch(): Vue.Ref<boolean> {
|
|
38
|
+
return Vue.inject(dummyPendingMatchContext, Vue.ref(false))
|
|
41
39
|
}
|
package/src/not-found.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as Vue from 'vue'
|
|
2
2
|
import { isNotFound } from '@tanstack/router-core'
|
|
3
|
+
import { useStore } from '@tanstack/vue-store'
|
|
3
4
|
import { CatchBoundary } from './CatchBoundary'
|
|
4
|
-
import {
|
|
5
|
+
import { useRouter } from './useRouter'
|
|
5
6
|
import type { ErrorComponentProps, NotFoundError } from '@tanstack/router-core'
|
|
6
7
|
|
|
7
8
|
export function CatchNotFound(props: {
|
|
@@ -9,10 +10,13 @@ export function CatchNotFound(props: {
|
|
|
9
10
|
onCatch?: (error: Error) => void
|
|
10
11
|
children: Vue.VNode
|
|
11
12
|
}) {
|
|
13
|
+
const router = useRouter()
|
|
12
14
|
// TODO: Some way for the user to programmatically reset the not-found boundary?
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const pathname = useStore(
|
|
16
|
+
router.stores.location,
|
|
17
|
+
(location) => location.pathname,
|
|
18
|
+
)
|
|
19
|
+
const status = useStore(router.stores.status, (value) => value)
|
|
16
20
|
|
|
17
21
|
// Create a function that returns a VNode to match the SyncRouteComponent signature
|
|
18
22
|
const errorComponentFn = (componentProps: ErrorComponentProps) => {
|
|
@@ -32,7 +36,7 @@ export function CatchNotFound(props: {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
return Vue.h(CatchBoundary, {
|
|
35
|
-
getResetKey: () =>
|
|
39
|
+
getResetKey: () => `not-found-${pathname.value}-${status.value}`,
|
|
36
40
|
onCatch: (error: Error) => {
|
|
37
41
|
if (isNotFound(error)) {
|
|
38
42
|
if (props.onCatch) {
|
package/src/router.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RouterCore } from '@tanstack/router-core'
|
|
2
|
+
import { getStoreFactory } from './routerStores'
|
|
2
3
|
import type { RouterHistory } from '@tanstack/history'
|
|
3
4
|
import type {
|
|
4
5
|
AnyRoute,
|
|
@@ -98,6 +99,6 @@ export class Router<
|
|
|
98
99
|
TDehydrated
|
|
99
100
|
>,
|
|
100
101
|
) {
|
|
101
|
-
super(options)
|
|
102
|
+
super(options, getStoreFactory)
|
|
102
103
|
}
|
|
103
104
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { batch, createStore } from '@tanstack/vue-store'
|
|
2
|
+
import type {
|
|
3
|
+
AnyRoute,
|
|
4
|
+
GetStoreConfig,
|
|
5
|
+
RouterStores,
|
|
6
|
+
} from '@tanstack/router-core'
|
|
7
|
+
import type { Readable } from '@tanstack/vue-store'
|
|
8
|
+
|
|
9
|
+
declare module '@tanstack/router-core' {
|
|
10
|
+
export interface RouterReadableStore<TValue> extends Readable<TValue> {}
|
|
11
|
+
export interface RouterStores<in out TRouteTree extends AnyRoute> {
|
|
12
|
+
/** Maps each active routeId to the matchId of its child in the match tree. */
|
|
13
|
+
childMatchIdByRouteId: RouterReadableStore<Record<string, string>>
|
|
14
|
+
/** Maps each pending routeId to true for quick lookup. */
|
|
15
|
+
pendingRouteIds: RouterReadableStore<Record<string, boolean>>
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const getStoreFactory: GetStoreConfig = (_opts) => {
|
|
20
|
+
return {
|
|
21
|
+
createMutableStore: createStore,
|
|
22
|
+
createReadonlyStore: createStore,
|
|
23
|
+
batch,
|
|
24
|
+
init: (stores: RouterStores<AnyRoute>) => {
|
|
25
|
+
// Single derived store: one reactive node that maps every active
|
|
26
|
+
// routeId to its child's matchId. Depends only on matchesId +
|
|
27
|
+
// the pool's routeId tags (which are set during reconciliation).
|
|
28
|
+
// Outlet reads the map and then does a direct pool lookup.
|
|
29
|
+
stores.childMatchIdByRouteId = createStore(() => {
|
|
30
|
+
const ids = stores.matchesId.state
|
|
31
|
+
const obj: Record<string, string> = {}
|
|
32
|
+
for (let i = 0; i < ids.length - 1; i++) {
|
|
33
|
+
const parentStore = stores.activeMatchStoresById.get(ids[i]!)
|
|
34
|
+
if (parentStore?.routeId) {
|
|
35
|
+
obj[parentStore.routeId] = ids[i + 1]!
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return obj
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
stores.pendingRouteIds = createStore(() => {
|
|
42
|
+
const ids = stores.pendingMatchesId.state
|
|
43
|
+
const obj: Record<string, boolean> = {}
|
|
44
|
+
for (const id of ids) {
|
|
45
|
+
const store = stores.pendingMatchStoresById.get(id)
|
|
46
|
+
if (store?.routeId) {
|
|
47
|
+
obj[store.routeId] = true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return obj
|
|
51
|
+
})
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/ssr/RouterClient.tsx
CHANGED
|
@@ -18,7 +18,7 @@ export const RouterClient = Vue.defineComponent({
|
|
|
18
18
|
const isHydrated = Vue.ref(false)
|
|
19
19
|
|
|
20
20
|
if (!hydrationPromise) {
|
|
21
|
-
if (!props.router.state.
|
|
21
|
+
if (!props.router.stores.matchesId.state.length) {
|
|
22
22
|
hydrationPromise = hydrate(props.router)
|
|
23
23
|
} else {
|
|
24
24
|
hydrationPromise = Promise.resolve()
|
|
@@ -62,7 +62,7 @@ export const renderRouterToStream = async ({
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
return new Response(`<!DOCTYPE html>${fullHtml}`, {
|
|
65
|
-
status: router.
|
|
65
|
+
status: router.stores.statusCode.state,
|
|
66
66
|
headers: responseHeaders,
|
|
67
67
|
})
|
|
68
68
|
}
|
|
@@ -78,7 +78,7 @@ export const renderRouterToStream = async ({
|
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
return new Response(responseStream as any, {
|
|
81
|
-
status: router.
|
|
81
|
+
status: router.stores.statusCode.state,
|
|
82
82
|
headers: responseHeaders,
|
|
83
83
|
})
|
|
84
84
|
}
|
package/src/useCanGoBack.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useStore } from '@tanstack/vue-store'
|
|
2
|
+
import { useRouter } from './useRouter'
|
|
2
3
|
|
|
3
4
|
export function useCanGoBack() {
|
|
4
|
-
|
|
5
|
+
const router = useRouter()
|
|
6
|
+
return useStore(
|
|
7
|
+
router.stores.location,
|
|
8
|
+
(location) => location.state.__TSR_index !== 0,
|
|
9
|
+
)
|
|
5
10
|
}
|
package/src/useLocation.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useStore } from '@tanstack/vue-store'
|
|
2
|
+
import { useRouter } from './useRouter'
|
|
2
3
|
import type {
|
|
3
4
|
AnyRouter,
|
|
4
5
|
RegisteredRouter,
|
|
@@ -23,8 +24,10 @@ export function useLocation<
|
|
|
23
24
|
>(
|
|
24
25
|
opts?: UseLocationBaseOptions<TRouter, TSelected>,
|
|
25
26
|
): Vue.Ref<UseLocationResult<TRouter, TSelected>> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const router = useRouter<TRouter>()
|
|
28
|
+
return useStore(
|
|
29
|
+
router.stores.location,
|
|
30
|
+
(location) =>
|
|
31
|
+
(opts?.select ? opts.select(location as any) : location) as any,
|
|
32
|
+
) as Vue.Ref<UseLocationResult<TRouter, TSelected>>
|
|
30
33
|
}
|
package/src/useMatch.tsx
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as Vue from 'vue'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useStore } from '@tanstack/vue-store'
|
|
3
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
4
|
+
import invariant from 'tiny-invariant'
|
|
5
|
+
import {
|
|
6
|
+
injectDummyPendingMatch,
|
|
7
|
+
injectPendingMatch,
|
|
8
|
+
routeIdContext,
|
|
9
|
+
} from './matchContext'
|
|
10
|
+
import { useRouter } from './useRouter'
|
|
4
11
|
import type {
|
|
5
12
|
AnyRouter,
|
|
6
13
|
MakeRouteMatch,
|
|
@@ -68,60 +75,99 @@ export function useMatch<
|
|
|
68
75
|
): Vue.Ref<
|
|
69
76
|
ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>
|
|
70
77
|
> {
|
|
71
|
-
const
|
|
78
|
+
const router = useRouter<TRouter>()
|
|
72
79
|
|
|
73
|
-
//
|
|
74
|
-
|
|
80
|
+
// During SSR we render exactly once and do not need reactivity.
|
|
81
|
+
// Avoid store subscriptions and pending/transition bookkeeping on the server.
|
|
82
|
+
if (isServer ?? router.isServer) {
|
|
83
|
+
const nearestRouteId = opts.from ? undefined : Vue.inject(routeIdContext)
|
|
84
|
+
const matchStore =
|
|
85
|
+
(opts.from ?? nearestRouteId)
|
|
86
|
+
? router.stores.getMatchStoreByRouteId(opts.from ?? nearestRouteId!)
|
|
87
|
+
: undefined
|
|
88
|
+
const match = matchStore?.state
|
|
75
89
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
invariant(
|
|
91
|
+
!((opts.shouldThrow ?? true) && !match),
|
|
92
|
+
`Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if (match === undefined) {
|
|
96
|
+
return Vue.ref(undefined) as Vue.Ref<
|
|
97
|
+
ThrowOrOptional<
|
|
98
|
+
UseMatchResult<TRouter, TFrom, TStrict, TSelected>,
|
|
99
|
+
TThrow
|
|
100
|
+
>
|
|
101
|
+
>
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return Vue.ref(opts.select ? opts.select(match) : match) as Vue.Ref<
|
|
105
|
+
ThrowOrOptional<
|
|
106
|
+
UseMatchResult<TRouter, TFrom, TStrict, TSelected>,
|
|
107
|
+
TThrow
|
|
108
|
+
>
|
|
109
|
+
>
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const hasPendingNearestMatch = opts.from
|
|
113
|
+
? injectDummyPendingMatch()
|
|
114
|
+
: injectPendingMatch()
|
|
115
|
+
// Set up reactive match value based on lookup strategy.
|
|
116
|
+
let match: Readonly<Vue.Ref<any>>
|
|
117
|
+
|
|
118
|
+
if (opts.from) {
|
|
119
|
+
// routeId case: single subscription via per-routeId computed store.
|
|
120
|
+
// The store reference is stable (cached by routeId).
|
|
121
|
+
const matchStore = router.stores.getMatchStoreByRouteId(opts.from)
|
|
122
|
+
match = useStore(matchStore, (value) => value)
|
|
123
|
+
} else {
|
|
124
|
+
// matchId case: use routeId from context for stable store lookup.
|
|
125
|
+
// The routeId is provided by the nearest Match component and doesn't
|
|
126
|
+
// change for the component's lifetime, so the store is stable.
|
|
127
|
+
const nearestRouteId = Vue.inject(routeIdContext)
|
|
128
|
+
if (nearestRouteId) {
|
|
129
|
+
match = useStore(
|
|
130
|
+
router.stores.getMatchStoreByRouteId(nearestRouteId),
|
|
131
|
+
(value) => value,
|
|
81
132
|
)
|
|
133
|
+
} else {
|
|
134
|
+
// No route context — will fall through to error handling below
|
|
135
|
+
match = Vue.ref(undefined) as Readonly<Vue.Ref<undefined>>
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const hasPendingRouteMatch = opts.from
|
|
140
|
+
? useStore(router.stores.pendingRouteIds, (ids) => ids)
|
|
141
|
+
: undefined
|
|
142
|
+
const isTransitioning = useStore(
|
|
143
|
+
router.stores.isTransitioning,
|
|
144
|
+
(value) => value,
|
|
145
|
+
{ equal: Object.is },
|
|
146
|
+
)
|
|
82
147
|
|
|
83
|
-
if (match === undefined) {
|
|
84
|
-
// During navigation transitions, check if the match exists in pendingMatches
|
|
85
|
-
const pendingMatch = state.pendingMatches?.find((d: any) =>
|
|
86
|
-
opts.from ? opts.from === d.routeId : d.id === nearestMatchId.value,
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
// If there's a pending match or we're transitioning, return undefined without throwing
|
|
90
|
-
if (pendingMatch || state.isTransitioning) {
|
|
91
|
-
pendingError.value = null
|
|
92
|
-
return undefined
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Store the error to throw later if shouldThrow is enabled
|
|
96
|
-
if (opts.shouldThrow ?? true) {
|
|
97
|
-
pendingError.value = new Error(
|
|
98
|
-
`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return undefined
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
pendingError.value = null
|
|
106
|
-
return opts.select ? opts.select(match) : match
|
|
107
|
-
},
|
|
108
|
-
} as any)
|
|
109
|
-
|
|
110
|
-
// Throw the error if we have one - this happens after the selector runs
|
|
111
|
-
// Using a computed so the error is thrown when the return value is accessed
|
|
112
148
|
const result = Vue.computed(() => {
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
|
|
149
|
+
const selectedMatch = match.value
|
|
150
|
+
if (selectedMatch === undefined) {
|
|
151
|
+
const hasPendingMatch = opts.from
|
|
152
|
+
? Boolean(hasPendingRouteMatch?.value[opts.from!])
|
|
153
|
+
: hasPendingNearestMatch.value
|
|
154
|
+
invariant(
|
|
155
|
+
!(
|
|
156
|
+
!hasPendingMatch &&
|
|
157
|
+
!isTransitioning.value &&
|
|
158
|
+
(opts.shouldThrow ?? true)
|
|
159
|
+
),
|
|
160
|
+
`Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
return undefined
|
|
116
164
|
}
|
|
117
|
-
|
|
165
|
+
|
|
166
|
+
return opts.select ? opts.select(selectedMatch) : selectedMatch
|
|
118
167
|
})
|
|
119
168
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
if (pendingError.value) {
|
|
123
|
-
throw pendingError.value
|
|
124
|
-
}
|
|
169
|
+
// Keep eager throw behavior for setups that call useMatch for side effects only.
|
|
170
|
+
result.value
|
|
125
171
|
|
|
126
|
-
return result
|
|
172
|
+
return result
|
|
127
173
|
}
|
package/src/useRouterState.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useStore } from '@tanstack/vue-store'
|
|
2
1
|
import * as Vue from 'vue'
|
|
3
2
|
import { isServer } from '@tanstack/router-core/isServer'
|
|
3
|
+
import { useStore } from '@tanstack/vue-store'
|
|
4
4
|
import { useRouter } from './useRouter'
|
|
5
5
|
import type {
|
|
6
6
|
AnyRouter,
|
|
@@ -30,7 +30,7 @@ export function useRouterState<
|
|
|
30
30
|
const router = opts?.router || contextRouter
|
|
31
31
|
|
|
32
32
|
// Return a safe default if router is undefined
|
|
33
|
-
if (!router || !router.__store) {
|
|
33
|
+
if (!router || !router.stores.__store) {
|
|
34
34
|
return Vue.ref(undefined) as Vue.Ref<
|
|
35
35
|
UseRouterStateResult<TRouter, TSelected>
|
|
36
36
|
>
|
|
@@ -42,13 +42,15 @@ export function useRouterState<
|
|
|
42
42
|
const _isServer = isServer ?? router.isServer
|
|
43
43
|
|
|
44
44
|
if (_isServer) {
|
|
45
|
-
const state = router.state as RouterState<
|
|
45
|
+
const state = router.stores.__store.state as RouterState<
|
|
46
|
+
TRouter['routeTree']
|
|
47
|
+
>
|
|
46
48
|
return Vue.ref(opts?.select ? opts.select(state) : state) as Vue.Ref<
|
|
47
49
|
UseRouterStateResult<TRouter, TSelected>
|
|
48
50
|
>
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
return useStore(router.__store, (state) => {
|
|
53
|
+
return useStore(router.stores.__store, (state) => {
|
|
52
54
|
if (opts?.select) return opts.select(state)
|
|
53
55
|
|
|
54
56
|
return state
|