@tanstack/solid-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.
Files changed (177) hide show
  1. package/dist/cjs/Match.cjs +244 -223
  2. package/dist/cjs/Match.cjs.map +1 -1
  3. package/dist/cjs/Match.d.cts +1 -3
  4. package/dist/cjs/Matches.cjs +32 -31
  5. package/dist/cjs/Matches.cjs.map +1 -1
  6. package/dist/cjs/Scripts.cjs +10 -8
  7. package/dist/cjs/Scripts.cjs.map +1 -1
  8. package/dist/cjs/Scripts.d.cts +2 -1
  9. package/dist/cjs/Transitioner.cjs +26 -26
  10. package/dist/cjs/Transitioner.cjs.map +1 -1
  11. package/dist/cjs/headContentUtils.cjs +15 -15
  12. package/dist/cjs/headContentUtils.cjs.map +1 -1
  13. package/dist/cjs/index.cjs +1 -1
  14. package/dist/cjs/index.dev.cjs +1 -1
  15. package/dist/cjs/link.cjs +119 -84
  16. package/dist/cjs/link.cjs.map +1 -1
  17. package/dist/cjs/matchContext.cjs +7 -5
  18. package/dist/cjs/matchContext.cjs.map +1 -1
  19. package/dist/cjs/matchContext.d.cts +8 -2
  20. package/dist/cjs/not-found.cjs +8 -4
  21. package/dist/cjs/not-found.cjs.map +1 -1
  22. package/dist/cjs/not-found.d.cts +1 -1
  23. package/dist/cjs/router.cjs +2 -1
  24. package/dist/cjs/router.cjs.map +1 -1
  25. package/dist/cjs/routerStores.cjs +67 -0
  26. package/dist/cjs/routerStores.cjs.map +1 -0
  27. package/dist/cjs/routerStores.d.cts +10 -0
  28. package/dist/cjs/ssr/RouterClient.cjs +1 -1
  29. package/dist/cjs/ssr/RouterClient.cjs.map +1 -1
  30. package/dist/cjs/ssr/renderRouterToStream.cjs +1 -1
  31. package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -1
  32. package/dist/cjs/ssr/renderRouterToString.cjs +2 -2
  33. package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -1
  34. package/dist/cjs/ssr/renderRouterToString.d.cts +1 -1
  35. package/dist/cjs/useCanGoBack.cjs +6 -2
  36. package/dist/cjs/useCanGoBack.cjs.map +1 -1
  37. package/dist/cjs/useCanGoBack.d.cts +2 -1
  38. package/dist/cjs/useLoaderDeps.cjs +2 -3
  39. package/dist/cjs/useLoaderDeps.cjs.map +1 -1
  40. package/dist/cjs/useLocation.cjs +13 -2
  41. package/dist/cjs/useLocation.cjs.map +1 -1
  42. package/dist/cjs/useMatch.cjs +17 -15
  43. package/dist/cjs/useMatch.cjs.map +1 -1
  44. package/dist/cjs/useParams.cjs +1 -1
  45. package/dist/cjs/useParams.cjs.map +1 -1
  46. package/dist/cjs/useRouterState.cjs +12 -19
  47. package/dist/cjs/useRouterState.cjs.map +1 -1
  48. package/dist/cjs/useSearch.cjs +2 -1
  49. package/dist/cjs/useSearch.cjs.map +1 -1
  50. package/dist/cjs/utils.cjs +0 -14
  51. package/dist/cjs/utils.cjs.map +1 -1
  52. package/dist/cjs/utils.d.cts +0 -4
  53. package/dist/esm/Match.d.ts +1 -3
  54. package/dist/esm/Match.js +245 -224
  55. package/dist/esm/Match.js.map +1 -1
  56. package/dist/esm/Matches.js +34 -33
  57. package/dist/esm/Matches.js.map +1 -1
  58. package/dist/esm/Scripts.d.ts +2 -1
  59. package/dist/esm/Scripts.js +8 -7
  60. package/dist/esm/Scripts.js.map +1 -1
  61. package/dist/esm/Transitioner.js +26 -26
  62. package/dist/esm/Transitioner.js.map +1 -1
  63. package/dist/esm/headContentUtils.js +15 -15
  64. package/dist/esm/headContentUtils.js.map +1 -1
  65. package/dist/esm/index.dev.js +1 -1
  66. package/dist/esm/index.js +1 -1
  67. package/dist/esm/link.js +120 -85
  68. package/dist/esm/link.js.map +1 -1
  69. package/dist/esm/matchContext.d.ts +8 -2
  70. package/dist/esm/matchContext.js +7 -4
  71. package/dist/esm/matchContext.js.map +1 -1
  72. package/dist/esm/not-found.d.ts +1 -1
  73. package/dist/esm/not-found.js +6 -3
  74. package/dist/esm/not-found.js.map +1 -1
  75. package/dist/esm/router.js +2 -1
  76. package/dist/esm/router.js.map +1 -1
  77. package/dist/esm/routerStores.d.ts +10 -0
  78. package/dist/esm/routerStores.js +65 -0
  79. package/dist/esm/routerStores.js.map +1 -0
  80. package/dist/esm/ssr/RouterClient.js +1 -1
  81. package/dist/esm/ssr/RouterClient.js.map +1 -1
  82. package/dist/esm/ssr/renderRouterToStream.js +1 -1
  83. package/dist/esm/ssr/renderRouterToStream.js.map +1 -1
  84. package/dist/esm/ssr/renderRouterToString.d.ts +1 -1
  85. package/dist/esm/ssr/renderRouterToString.js +2 -2
  86. package/dist/esm/ssr/renderRouterToString.js.map +1 -1
  87. package/dist/esm/useCanGoBack.d.ts +2 -1
  88. package/dist/esm/useCanGoBack.js +4 -2
  89. package/dist/esm/useCanGoBack.js.map +1 -1
  90. package/dist/esm/useLoaderDeps.js +2 -3
  91. package/dist/esm/useLoaderDeps.js.map +1 -1
  92. package/dist/esm/useLocation.js +11 -2
  93. package/dist/esm/useLocation.js.map +1 -1
  94. package/dist/esm/useMatch.js +18 -16
  95. package/dist/esm/useMatch.js.map +1 -1
  96. package/dist/esm/useParams.js +1 -1
  97. package/dist/esm/useParams.js.map +1 -1
  98. package/dist/esm/useRouterState.js +10 -18
  99. package/dist/esm/useRouterState.js.map +1 -1
  100. package/dist/esm/useSearch.js +2 -1
  101. package/dist/esm/useSearch.js.map +1 -1
  102. package/dist/esm/utils.d.ts +0 -4
  103. package/dist/esm/utils.js +1 -14
  104. package/dist/esm/utils.js.map +1 -1
  105. package/dist/source/Match.d.ts +1 -3
  106. package/dist/source/Match.jsx +246 -237
  107. package/dist/source/Match.jsx.map +1 -1
  108. package/dist/source/Matches.jsx +42 -44
  109. package/dist/source/Matches.jsx.map +1 -1
  110. package/dist/source/Scripts.d.ts +2 -1
  111. package/dist/source/Scripts.jsx +31 -36
  112. package/dist/source/Scripts.jsx.map +1 -1
  113. package/dist/source/Transitioner.jsx +26 -31
  114. package/dist/source/Transitioner.jsx.map +1 -1
  115. package/dist/source/headContentUtils.jsx +64 -72
  116. package/dist/source/headContentUtils.jsx.map +1 -1
  117. package/dist/source/link.jsx +136 -107
  118. package/dist/source/link.jsx.map +1 -1
  119. package/dist/source/matchContext.d.ts +8 -2
  120. package/dist/source/matchContext.jsx +7 -3
  121. package/dist/source/matchContext.jsx.map +1 -1
  122. package/dist/source/not-found.d.ts +1 -1
  123. package/dist/source/not-found.jsx +6 -5
  124. package/dist/source/not-found.jsx.map +1 -1
  125. package/dist/source/router.js +2 -1
  126. package/dist/source/router.js.map +1 -1
  127. package/dist/source/routerStores.d.ts +10 -0
  128. package/dist/source/routerStores.js +71 -0
  129. package/dist/source/routerStores.js.map +1 -0
  130. package/dist/source/ssr/RouterClient.jsx +1 -1
  131. package/dist/source/ssr/RouterClient.jsx.map +1 -1
  132. package/dist/source/ssr/renderRouterToStream.jsx +1 -1
  133. package/dist/source/ssr/renderRouterToStream.jsx.map +1 -1
  134. package/dist/source/ssr/renderRouterToString.d.ts +1 -1
  135. package/dist/source/ssr/renderRouterToString.jsx +2 -2
  136. package/dist/source/ssr/renderRouterToString.jsx.map +1 -1
  137. package/dist/source/useCanGoBack.d.ts +2 -1
  138. package/dist/source/useCanGoBack.js +4 -2
  139. package/dist/source/useCanGoBack.js.map +1 -1
  140. package/dist/source/useLoaderDeps.jsx +2 -3
  141. package/dist/source/useLoaderDeps.jsx.map +1 -1
  142. package/dist/source/useLocation.jsx +13 -3
  143. package/dist/source/useLocation.jsx.map +1 -1
  144. package/dist/source/useMatch.jsx +30 -27
  145. package/dist/source/useMatch.jsx.map +1 -1
  146. package/dist/source/useParams.jsx +1 -1
  147. package/dist/source/useParams.jsx.map +1 -1
  148. package/dist/source/useRouterState.jsx +12 -33
  149. package/dist/source/useRouterState.jsx.map +1 -1
  150. package/dist/source/useSearch.jsx +2 -1
  151. package/dist/source/useSearch.jsx.map +1 -1
  152. package/dist/source/utils.d.ts +0 -4
  153. package/dist/source/utils.js +0 -13
  154. package/dist/source/utils.js.map +1 -1
  155. package/package.json +2 -3
  156. package/skills/solid-router/SKILL.md +2 -0
  157. package/src/Match.tsx +351 -304
  158. package/src/Matches.tsx +49 -52
  159. package/src/Scripts.tsx +40 -41
  160. package/src/Transitioner.tsx +67 -66
  161. package/src/headContentUtils.tsx +89 -91
  162. package/src/link.tsx +179 -141
  163. package/src/matchContext.tsx +16 -7
  164. package/src/not-found.tsx +6 -6
  165. package/src/router.ts +2 -1
  166. package/src/routerStores.ts +107 -0
  167. package/src/ssr/RouterClient.tsx +1 -1
  168. package/src/ssr/renderRouterToStream.tsx +1 -1
  169. package/src/ssr/renderRouterToString.tsx +2 -2
  170. package/src/useCanGoBack.ts +6 -2
  171. package/src/useLoaderDeps.tsx +2 -3
  172. package/src/useLocation.tsx +18 -5
  173. package/src/useMatch.tsx +36 -43
  174. package/src/useParams.tsx +2 -3
  175. package/src/useRouterState.tsx +17 -41
  176. package/src/useSearch.tsx +2 -1
  177. package/src/utils.ts +0 -20
package/src/Matches.tsx CHANGED
@@ -1,12 +1,11 @@
1
1
  import * as Solid from 'solid-js'
2
2
  import warning from 'tiny-warning'
3
- import { rootRouteId } from '@tanstack/router-core'
3
+ import { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'
4
4
  import { isServer } from '@tanstack/router-core/isServer'
5
5
  import { CatchBoundary, ErrorComponent } from './CatchBoundary'
6
- import { useRouterState } from './useRouterState'
7
6
  import { useRouter } from './useRouter'
8
7
  import { Transitioner } from './Transitioner'
9
- import { matchContext } from './matchContext'
8
+ import { nearestMatchContext } from './matchContext'
10
9
  import { SafeFragment } from './SafeFragment'
11
10
  import { Match } from './Match'
12
11
  import type {
@@ -24,7 +23,6 @@ import type {
24
23
  ResolveRelativePath,
25
24
  ResolveRoute,
26
25
  RouteByPath,
27
- RouterState,
28
26
  ToSubOptionsProps,
29
27
  } from '@tanstack/router-core'
30
28
 
@@ -68,15 +66,23 @@ export function Matches() {
68
66
 
69
67
  function MatchesInner() {
70
68
  const router = useRouter()
71
- const matchId = useRouterState({
72
- select: (s) => {
73
- return s.matches[0]?.id
74
- },
75
- })
76
-
77
- const resetKey = useRouterState({
78
- select: (s) => s.loadedAt,
79
- })
69
+ const matchId = () => router.stores.firstMatchId.state
70
+ const routeId = () => (matchId() ? rootRouteId : undefined)
71
+ const match = () =>
72
+ routeId()
73
+ ? router.stores.getMatchStoreByRouteId(rootRouteId).state
74
+ : undefined
75
+ const hasPendingMatch = () =>
76
+ routeId()
77
+ ? Boolean(router.stores.pendingRouteIds.state[rootRouteId])
78
+ : false
79
+ const resetKey = () => router.stores.loadedAt.state
80
+ const nearestMatch = {
81
+ matchId,
82
+ routeId,
83
+ match,
84
+ hasPending: hasPendingMatch,
85
+ }
80
86
 
81
87
  const matchComponent = () => {
82
88
  return (
@@ -87,7 +93,7 @@ function MatchesInner() {
87
93
  }
88
94
 
89
95
  return (
90
- <matchContext.Provider value={matchId}>
96
+ <nearestMatchContext.Provider value={nearestMatch}>
91
97
  {router.options.disableGlobalCatchBoundary ? (
92
98
  matchComponent()
93
99
  ) : (
@@ -99,8 +105,7 @@ function MatchesInner() {
99
105
  ? (error) => {
100
106
  warning(
101
107
  false,
102
- `The following error wasn't caught by any route! At the very leas
103
- t, consider setting an 'errorComponent' in your RootRoute!`,
108
+ `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
104
109
  )
105
110
  warning(false, error.message || error.toString())
106
111
  }
@@ -110,7 +115,7 @@ function MatchesInner() {
110
115
  {matchComponent()}
111
116
  </CatchBoundary>
112
117
  )}
113
- </matchContext.Provider>
118
+ </nearestMatchContext.Provider>
114
119
  )
115
120
  }
116
121
 
@@ -129,10 +134,6 @@ export type UseMatchRouteOptions<
129
134
  export function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {
130
135
  const router = useRouter()
131
136
 
132
- const status = useRouterState({
133
- select: (s) => s.status,
134
- })
135
-
136
137
  return <
137
138
  const TFrom extends string = string,
138
139
  const TTo extends string | undefined = undefined,
@@ -143,10 +144,10 @@ export function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {
143
144
  ): Solid.Accessor<
144
145
  false | Expand<ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']>
145
146
  > => {
146
- const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts
147
+ return Solid.createMemo(() => {
148
+ const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts
147
149
 
148
- const matchRoute = Solid.createMemo(() => {
149
- status()
150
+ router.stores.matchRouteReactivity.state
150
151
  return router.matchRoute(rest as any, {
151
152
  pending,
152
153
  caseSensitive,
@@ -154,8 +155,6 @@ export function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {
154
155
  includeSearch,
155
156
  })
156
157
  })
157
-
158
- return matchRoute
159
158
  }
160
159
  }
161
160
 
@@ -184,24 +183,21 @@ export function MatchRoute<
184
183
  const TMaskFrom extends string = TFrom,
185
184
  const TMaskTo extends string = '',
186
185
  >(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {
187
- const status = useRouterState({
188
- select: (s) => s.status,
189
- })
186
+ const matchRoute = useMatchRoute()
187
+ const params = matchRoute(props as any)
190
188
 
191
- return (
192
- <Solid.Show when={status()} keyed>
193
- {(_) => {
194
- const matchRoute = useMatchRoute()
195
- const params = matchRoute(props as any)() as boolean
196
- const child = props.children
197
- if (typeof child === 'function') {
198
- return (child as any)(params)
199
- }
189
+ const renderedChild = Solid.createMemo(() => {
190
+ const matchedParams = params()
191
+ const child = props.children
200
192
 
201
- return params ? child : null
202
- }}
203
- </Solid.Show>
204
- )
193
+ if (typeof child === 'function') {
194
+ return (child as any)(matchedParams)
195
+ }
196
+
197
+ return matchedParams ? child : null
198
+ })
199
+
200
+ return <>{renderedChild()}</>
205
201
  }
206
202
 
207
203
  export interface UseMatchesBaseOptions<TRouter extends AnyRouter, TSelected> {
@@ -219,14 +215,15 @@ export function useMatches<
219
215
  >(
220
216
  opts?: UseMatchesBaseOptions<TRouter, TSelected>,
221
217
  ): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {
222
- return useRouterState({
223
- select: (state: RouterState<TRouter['routeTree']>) => {
224
- const matches = state.matches
225
- return opts?.select
226
- ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)
227
- : matches
228
- },
229
- } as any) as Solid.Accessor<UseMatchesResult<TRouter, TSelected>>
218
+ const router = useRouter<TRouter>()
219
+ return Solid.createMemo((prev: TSelected | undefined) => {
220
+ const matches = router.stores.activeMatchesSnapshot.state as Array<
221
+ MakeRouteMatchUnion<TRouter>
222
+ >
223
+ const res = opts?.select ? opts.select(matches) : matches
224
+ if (prev === undefined) return res
225
+ return replaceEqualDeep(prev, res) as any
226
+ }) as Solid.Accessor<UseMatchesResult<TRouter, TSelected>>
230
227
  }
231
228
 
232
229
  export function useParentMatches<
@@ -235,7 +232,7 @@ export function useParentMatches<
235
232
  >(
236
233
  opts?: UseMatchesBaseOptions<TRouter, TSelected>,
237
234
  ): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {
238
- const contextMatchId = Solid.useContext(matchContext)
235
+ const contextMatchId = Solid.useContext(nearestMatchContext).matchId
239
236
 
240
237
  return useMatches({
241
238
  select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
@@ -254,7 +251,7 @@ export function useChildMatches<
254
251
  >(
255
252
  opts?: UseMatchesBaseOptions<TRouter, TSelected>,
256
253
  ): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {
257
- const contextMatchId = Solid.useContext(matchContext)
254
+ const contextMatchId = Solid.useContext(nearestMatchContext).matchId
258
255
 
259
256
  return useMatches({
260
257
  select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
package/src/Scripts.tsx CHANGED
@@ -1,55 +1,54 @@
1
+ import * as Solid from 'solid-js'
1
2
  import { Asset } from './Asset'
2
- import { useRouterState } from './useRouterState'
3
3
  import { useRouter } from './useRouter'
4
4
  import type { RouterManagedTag } from '@tanstack/router-core'
5
5
 
6
6
  export const Scripts = () => {
7
7
  const router = useRouter()
8
8
  const nonce = router.options.ssr?.nonce
9
- const assetScripts = useRouterState({
10
- select: (state) => {
11
- const assetScripts: Array<RouterManagedTag> = []
12
- const manifest = router.ssr?.manifest
9
+ const activeMatches = Solid.createMemo(
10
+ () => router.stores.activeMatchesSnapshot.state,
11
+ )
12
+ const assetScripts = Solid.createMemo(() => {
13
+ const assetScripts: Array<RouterManagedTag> = []
14
+ const manifest = router.ssr?.manifest
13
15
 
14
- if (!manifest) {
15
- return []
16
- }
16
+ if (!manifest) {
17
+ return []
18
+ }
17
19
 
18
- state.matches
19
- .map((match) => router.looseRoutesById[match.routeId]!)
20
- .forEach((route) =>
21
- manifest.routes[route.id]?.assets
22
- ?.filter((d) => d.tag === 'script')
23
- .forEach((asset) => {
24
- assetScripts.push({
25
- tag: 'script',
26
- attrs: { ...asset.attrs, nonce },
27
- children: asset.children,
28
- } as any)
29
- }),
30
- )
20
+ activeMatches()
21
+ .map((match) => router.looseRoutesById[match.routeId]!)
22
+ .forEach((route) =>
23
+ manifest.routes[route.id]?.assets
24
+ ?.filter((d) => d.tag === 'script')
25
+ .forEach((asset) => {
26
+ assetScripts.push({
27
+ tag: 'script',
28
+ attrs: { ...asset.attrs, nonce },
29
+ children: asset.children,
30
+ } as any)
31
+ }),
32
+ )
31
33
 
32
- return assetScripts
33
- },
34
+ return assetScripts
34
35
  })
35
36
 
36
- const scripts = useRouterState({
37
- select: (state) => ({
38
- scripts: (
39
- state.matches
40
- .map((match) => match.scripts!)
41
- .flat(1)
42
- .filter(Boolean) as Array<RouterManagedTag>
43
- ).map(({ children, ...script }) => ({
44
- tag: 'script',
45
- attrs: {
46
- ...script,
47
- nonce,
48
- },
49
- children,
50
- })),
51
- }),
52
- })
37
+ const scripts = Solid.createMemo(() =>
38
+ (
39
+ activeMatches()
40
+ .map((match) => match.scripts!)
41
+ .flat(1)
42
+ .filter(Boolean) as Array<RouterManagedTag>
43
+ ).map(({ children, ...script }) => ({
44
+ tag: 'script',
45
+ attrs: {
46
+ ...script,
47
+ nonce,
48
+ },
49
+ children,
50
+ })),
51
+ )
53
52
 
54
53
  let serverBufferedScript: RouterManagedTag | undefined = undefined
55
54
 
@@ -58,7 +57,7 @@ export const Scripts = () => {
58
57
  }
59
58
 
60
59
  const allScripts = [
61
- ...scripts().scripts,
60
+ ...scripts(),
62
61
  ...assetScripts(),
63
62
  ] as Array<RouterManagedTag>
64
63
 
@@ -6,15 +6,11 @@ import {
6
6
  } from '@tanstack/router-core'
7
7
  import { isServer } from '@tanstack/router-core/isServer'
8
8
  import { useRouter } from './useRouter'
9
- import { useRouterState } from './useRouterState'
10
- import { usePrevious } from './utils'
11
9
 
12
10
  export function Transitioner() {
13
11
  const router = useRouter()
14
12
  let mountLoadForRouter = { router, mounted: false }
15
- const isLoading = useRouterState({
16
- select: ({ isLoading }) => isLoading,
17
- })
13
+ const isLoading = Solid.createMemo(() => router.stores.isLoading.state)
18
14
 
19
15
  if (isServer ?? router.isServer) {
20
16
  return null
@@ -23,18 +19,17 @@ export function Transitioner() {
23
19
  const [isSolidTransitioning, startSolidTransition] = Solid.useTransition()
24
20
 
25
21
  // Track pending state changes
26
- const hasPendingMatches = useRouterState({
27
- select: (s) => s.matches.some((d) => d.status === 'pending'),
28
- })
29
-
30
- const previousIsLoading = usePrevious(isLoading)
22
+ const hasPendingMatches = Solid.createMemo(
23
+ () => router.stores.hasPendingMatches.state,
24
+ )
31
25
 
32
- const isAnyPending = () =>
33
- isLoading() || isSolidTransitioning() || hasPendingMatches()
34
- const previousIsAnyPending = usePrevious(isAnyPending)
26
+ const isAnyPending = Solid.createMemo(
27
+ () => isLoading() || isSolidTransitioning() || hasPendingMatches(),
28
+ )
35
29
 
36
- const isPagePending = () => isLoading() || hasPendingMatches()
37
- const previousIsPagePending = usePrevious(isPagePending)
30
+ const isPagePending = Solid.createMemo(
31
+ () => isLoading() || hasPendingMatches(),
32
+ )
38
33
 
39
34
  router.startTransition = (fn: () => void | Promise<void>) => {
40
35
  Solid.startTransition(() => {
@@ -93,59 +88,65 @@ export function Transitioner() {
93
88
  })
94
89
  })
95
90
 
96
- Solid.createRenderEffect(
97
- Solid.on(
98
- [previousIsLoading, isLoading],
99
- ([previousIsLoading, isLoading]) => {
100
- if (previousIsLoading.previous && !isLoading) {
101
- router.emit({
102
- type: 'onLoad',
103
- ...getLocationChangeInfo(router.state),
104
- })
105
- }
106
- },
107
- ),
108
- )
91
+ Solid.createRenderEffect((previousIsLoading = false) => {
92
+ const currentIsLoading = isLoading()
93
+
94
+ if (previousIsLoading && !currentIsLoading) {
95
+ router.emit({
96
+ type: 'onLoad',
97
+ ...getLocationChangeInfo(
98
+ router.stores.location.state,
99
+ router.stores.resolvedLocation.state,
100
+ ),
101
+ })
102
+ }
109
103
 
110
- Solid.createComputed(
111
- Solid.on(
112
- [isPagePending, previousIsPagePending],
113
- ([isPagePending, previousIsPagePending]) => {
114
- // emit onBeforeRouteMount
115
- if (previousIsPagePending.previous && !isPagePending) {
116
- router.emit({
117
- type: 'onBeforeRouteMount',
118
- ...getLocationChangeInfo(router.state),
119
- })
120
- }
121
- },
122
- ),
123
- )
104
+ return currentIsLoading
105
+ })
124
106
 
125
- Solid.createRenderEffect(
126
- Solid.on(
127
- [isAnyPending, previousIsAnyPending],
128
- ([isAnyPending, previousIsAnyPending]) => {
129
- if (previousIsAnyPending.previous && !isAnyPending) {
130
- const changeInfo = getLocationChangeInfo(router.state)
131
- router.emit({
132
- type: 'onResolved',
133
- ...changeInfo,
134
- })
135
-
136
- router.__store.setState((s) => ({
137
- ...s,
138
- status: 'idle',
139
- resolvedLocation: s.location,
140
- }))
141
-
142
- if (changeInfo.hrefChanged) {
143
- handleHashScroll(router)
144
- }
145
- }
146
- },
147
- ),
148
- )
107
+ Solid.createComputed((previousIsPagePending = false) => {
108
+ const currentIsPagePending = isPagePending()
109
+
110
+ if (previousIsPagePending && !currentIsPagePending) {
111
+ router.emit({
112
+ type: 'onBeforeRouteMount',
113
+ ...getLocationChangeInfo(
114
+ router.stores.location.state,
115
+ router.stores.resolvedLocation.state,
116
+ ),
117
+ })
118
+ }
119
+
120
+ return currentIsPagePending
121
+ })
122
+
123
+ Solid.createRenderEffect((previousIsAnyPending = false) => {
124
+ const currentIsAnyPending = isAnyPending()
125
+
126
+ if (previousIsAnyPending && !currentIsAnyPending) {
127
+ const changeInfo = getLocationChangeInfo(
128
+ router.stores.location.state,
129
+ router.stores.resolvedLocation.state,
130
+ )
131
+ router.emit({
132
+ type: 'onResolved',
133
+ ...changeInfo,
134
+ })
135
+
136
+ Solid.batch(() => {
137
+ router.stores.status.setState(() => 'idle')
138
+ router.stores.resolvedLocation.setState(
139
+ () => router.stores.location.state,
140
+ )
141
+ })
142
+
143
+ if (changeInfo.hrefChanged) {
144
+ handleHashScroll(router)
145
+ }
146
+ }
147
+
148
+ return currentIsAnyPending
149
+ })
149
150
 
150
151
  return null
151
152
  }
@@ -1,7 +1,6 @@
1
1
  import * as Solid from 'solid-js'
2
2
  import { escapeHtml } from '@tanstack/router-core'
3
3
  import { useRouter } from './useRouter'
4
- import { useRouterState } from './useRouterState'
5
4
  import type { RouterManagedTag } from '@tanstack/router-core'
6
5
 
7
6
  /**
@@ -11,11 +10,14 @@ import type { RouterManagedTag } from '@tanstack/router-core'
11
10
  export const useTags = () => {
12
11
  const router = useRouter()
13
12
  const nonce = router.options.ssr?.nonce
14
- const routeMeta = useRouterState({
15
- select: (state) => {
16
- return state.matches.map((match) => match.meta!).filter(Boolean)
17
- },
18
- })
13
+ const activeMatches = Solid.createMemo(
14
+ () => router.stores.activeMatchesSnapshot.state,
15
+ )
16
+ const routeMeta = Solid.createMemo(() =>
17
+ activeMatches()
18
+ .map((match) => match.meta!)
19
+ .filter(Boolean),
20
+ )
19
21
 
20
22
  const meta: Solid.Accessor<Array<RouterManagedTag>> = Solid.createMemo(() => {
21
23
  const resultMeta: Array<RouterManagedTag> = []
@@ -89,98 +91,94 @@ export const useTags = () => {
89
91
  return resultMeta
90
92
  })
91
93
 
92
- const links = useRouterState({
93
- select: (state) => {
94
- const constructed = state.matches
95
- .map((match) => match.links!)
96
- .filter(Boolean)
97
- .flat(1)
98
- .map((link) => ({
99
- tag: 'link',
100
- attrs: {
101
- ...link,
102
- nonce,
103
- },
104
- })) satisfies Array<RouterManagedTag>
105
-
106
- const manifest = router.ssr?.manifest
107
-
108
- const assets = state.matches
109
- .map((match) => manifest?.routes[match.routeId]?.assets ?? [])
110
- .filter(Boolean)
111
- .flat(1)
112
- .filter((asset) => asset.tag === 'link')
113
- .map(
114
- (asset) =>
115
- ({
116
- tag: 'link',
117
- attrs: { ...asset.attrs, nonce },
118
- }) satisfies RouterManagedTag,
119
- )
120
-
121
- return [...constructed, ...assets]
122
- },
123
- })
124
-
125
- const preloadLinks = useRouterState({
126
- select: (state) => {
127
- const preloadLinks: Array<RouterManagedTag> = []
128
-
129
- state.matches
130
- .map((match) => router.looseRoutesById[match.routeId]!)
131
- .forEach((route) =>
132
- router.ssr?.manifest?.routes[route.id]?.preloads
133
- ?.filter(Boolean)
134
- .forEach((preload) => {
135
- preloadLinks.push({
136
- tag: 'link',
137
- attrs: {
138
- rel: 'modulepreload',
139
- href: preload,
140
- nonce,
141
- },
142
- })
143
- }),
144
- )
145
-
146
- return preloadLinks
147
- },
148
- })
149
-
150
- const styles = useRouterState({
151
- select: (state) =>
152
- (
153
- state.matches
154
- .map((match) => match.styles!)
155
- .flat(1)
156
- .filter(Boolean) as Array<RouterManagedTag>
157
- ).map(({ children, ...style }) => ({
158
- tag: 'style',
94
+ const links = Solid.createMemo(() => {
95
+ const matches = activeMatches()
96
+ const constructed = matches
97
+ .map((match) => match.links!)
98
+ .filter(Boolean)
99
+ .flat(1)
100
+ .map((link) => ({
101
+ tag: 'link',
159
102
  attrs: {
160
- ...style,
103
+ ...link,
161
104
  nonce,
162
105
  },
163
- children,
164
- })),
106
+ })) satisfies Array<RouterManagedTag>
107
+
108
+ const manifest = router.ssr?.manifest
109
+
110
+ const assets = matches
111
+ .map((match) => manifest?.routes[match.routeId]?.assets ?? [])
112
+ .filter(Boolean)
113
+ .flat(1)
114
+ .filter((asset) => asset.tag === 'link')
115
+ .map(
116
+ (asset) =>
117
+ ({
118
+ tag: 'link',
119
+ attrs: { ...asset.attrs, nonce },
120
+ }) satisfies RouterManagedTag,
121
+ )
122
+
123
+ return [...constructed, ...assets]
165
124
  })
166
125
 
167
- const headScripts = useRouterState({
168
- select: (state) =>
169
- (
170
- state.matches
171
- .map((match) => match.headScripts!)
172
- .flat(1)
173
- .filter(Boolean) as Array<RouterManagedTag>
174
- ).map(({ children, ...script }) => ({
175
- tag: 'script',
176
- attrs: {
177
- ...script,
178
- nonce,
179
- },
180
- children,
181
- })),
126
+ const preloadLinks = Solid.createMemo(() => {
127
+ const matches = activeMatches()
128
+ const preloadLinks: Array<RouterManagedTag> = []
129
+
130
+ matches
131
+ .map((match) => router.looseRoutesById[match.routeId]!)
132
+ .forEach((route) =>
133
+ router.ssr?.manifest?.routes[route.id]?.preloads
134
+ ?.filter(Boolean)
135
+ .forEach((preload) => {
136
+ preloadLinks.push({
137
+ tag: 'link',
138
+ attrs: {
139
+ rel: 'modulepreload',
140
+ href: preload,
141
+ nonce,
142
+ },
143
+ })
144
+ }),
145
+ )
146
+
147
+ return preloadLinks
182
148
  })
183
149
 
150
+ const styles = Solid.createMemo(() =>
151
+ (
152
+ activeMatches()
153
+ .map((match) => match.styles!)
154
+ .flat(1)
155
+ .filter(Boolean) as Array<RouterManagedTag>
156
+ ).map(({ children, ...style }) => ({
157
+ tag: 'style',
158
+ attrs: {
159
+ ...style,
160
+ nonce,
161
+ },
162
+ children,
163
+ })),
164
+ )
165
+
166
+ const headScripts = Solid.createMemo(() =>
167
+ (
168
+ activeMatches()
169
+ .map((match) => match.headScripts!)
170
+ .flat(1)
171
+ .filter(Boolean) as Array<RouterManagedTag>
172
+ ).map(({ children, ...script }) => ({
173
+ tag: 'script',
174
+ attrs: {
175
+ ...script,
176
+ nonce,
177
+ },
178
+ children,
179
+ })),
180
+ )
181
+
184
182
  return () =>
185
183
  uniqBy(
186
184
  [