@tanstack/react-router 1.167.5 → 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 (89) hide show
  1. package/dist/cjs/Match.cjs +118 -52
  2. package/dist/cjs/Match.cjs.map +1 -1
  3. package/dist/cjs/Matches.cjs +20 -20
  4. package/dist/cjs/Matches.cjs.map +1 -1
  5. package/dist/cjs/Scripts.cjs +36 -32
  6. package/dist/cjs/Scripts.cjs.map +1 -1
  7. package/dist/cjs/Transitioner.cjs +10 -16
  8. package/dist/cjs/Transitioner.cjs.map +1 -1
  9. package/dist/cjs/headContentUtils.cjs +147 -59
  10. package/dist/cjs/headContentUtils.cjs.map +1 -1
  11. package/dist/cjs/index.cjs +1 -1
  12. package/dist/cjs/index.dev.cjs +1 -1
  13. package/dist/cjs/link.cjs +34 -29
  14. package/dist/cjs/link.cjs.map +1 -1
  15. package/dist/cjs/not-found.cjs +20 -2
  16. package/dist/cjs/not-found.cjs.map +1 -1
  17. package/dist/cjs/router.cjs +2 -1
  18. package/dist/cjs/router.cjs.map +1 -1
  19. package/dist/cjs/routerStores.cjs +21 -0
  20. package/dist/cjs/routerStores.cjs.map +1 -0
  21. package/dist/cjs/routerStores.d.cts +7 -0
  22. package/dist/cjs/ssr/RouterClient.cjs +1 -1
  23. package/dist/cjs/ssr/RouterClient.cjs.map +1 -1
  24. package/dist/cjs/ssr/renderRouterToStream.cjs +2 -2
  25. package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -1
  26. package/dist/cjs/ssr/renderRouterToString.cjs +1 -1
  27. package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -1
  28. package/dist/cjs/useCanGoBack.cjs +7 -2
  29. package/dist/cjs/useCanGoBack.cjs.map +1 -1
  30. package/dist/cjs/useLocation.cjs +21 -2
  31. package/dist/cjs/useLocation.cjs.map +1 -1
  32. package/dist/cjs/useMatch.cjs +29 -9
  33. package/dist/cjs/useMatch.cjs.map +1 -1
  34. package/dist/cjs/useRouterState.cjs +2 -2
  35. package/dist/cjs/useRouterState.cjs.map +1 -1
  36. package/dist/esm/Match.js +118 -52
  37. package/dist/esm/Match.js.map +1 -1
  38. package/dist/esm/Matches.js +21 -21
  39. package/dist/esm/Matches.js.map +1 -1
  40. package/dist/esm/Scripts.js +36 -32
  41. package/dist/esm/Scripts.js.map +1 -1
  42. package/dist/esm/Transitioner.js +10 -16
  43. package/dist/esm/Transitioner.js.map +1 -1
  44. package/dist/esm/headContentUtils.js +148 -60
  45. package/dist/esm/headContentUtils.js.map +1 -1
  46. package/dist/esm/index.dev.js +1 -1
  47. package/dist/esm/index.js +1 -1
  48. package/dist/esm/link.js +34 -29
  49. package/dist/esm/link.js.map +1 -1
  50. package/dist/esm/not-found.js +20 -2
  51. package/dist/esm/not-found.js.map +1 -1
  52. package/dist/esm/router.js +2 -1
  53. package/dist/esm/router.js.map +1 -1
  54. package/dist/esm/routerStores.d.ts +7 -0
  55. package/dist/esm/routerStores.js +20 -0
  56. package/dist/esm/routerStores.js.map +1 -0
  57. package/dist/esm/ssr/RouterClient.js +1 -1
  58. package/dist/esm/ssr/RouterClient.js.map +1 -1
  59. package/dist/esm/ssr/renderRouterToStream.js +2 -2
  60. package/dist/esm/ssr/renderRouterToStream.js.map +1 -1
  61. package/dist/esm/ssr/renderRouterToString.js +1 -1
  62. package/dist/esm/ssr/renderRouterToString.js.map +1 -1
  63. package/dist/esm/useCanGoBack.js +6 -2
  64. package/dist/esm/useCanGoBack.js.map +1 -1
  65. package/dist/esm/useLocation.js +20 -2
  66. package/dist/esm/useLocation.js.map +1 -1
  67. package/dist/esm/useMatch.js +29 -9
  68. package/dist/esm/useMatch.js.map +1 -1
  69. package/dist/esm/useRouterState.js +2 -2
  70. package/dist/esm/useRouterState.js.map +1 -1
  71. package/dist/llms/rules/api.d.ts +1 -1
  72. package/dist/llms/rules/api.js +3 -9
  73. package/package.json +2 -2
  74. package/src/Match.tsx +218 -78
  75. package/src/Matches.tsx +45 -25
  76. package/src/Scripts.tsx +72 -44
  77. package/src/Transitioner.tsx +24 -16
  78. package/src/headContentUtils.tsx +210 -27
  79. package/src/link.tsx +66 -71
  80. package/src/not-found.tsx +41 -4
  81. package/src/router.ts +2 -1
  82. package/src/routerStores.ts +26 -0
  83. package/src/ssr/RouterClient.tsx +1 -1
  84. package/src/ssr/renderRouterToStream.tsx +2 -2
  85. package/src/ssr/renderRouterToString.tsx +1 -1
  86. package/src/useCanGoBack.ts +14 -2
  87. package/src/useLocation.tsx +32 -5
  88. package/src/useMatch.tsx +61 -21
  89. package/src/useRouterState.tsx +4 -2
@@ -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.state.statusCode,
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.state.statusCode,
82
+ status: router.stores.statusCode.state,
83
83
  headers: responseHeaders,
84
84
  })
85
85
  }
@@ -21,7 +21,7 @@ export const renderRouterToString = async ({
21
21
  }
22
22
 
23
23
  return new Response(`<!DOCTYPE html>${html}`, {
24
- status: router.state.statusCode,
24
+ status: router.stores.statusCode.state,
25
25
  headers: responseHeaders,
26
26
  })
27
27
  } catch (error) {
@@ -1,5 +1,17 @@
1
- import { useRouterState } from './useRouterState'
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
- return useRouterState({ select: (s) => s.location.state.__TSR_index !== 0 })
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
  }
@@ -1,4 +1,8 @@
1
- import { useRouterState } from './useRouterState'
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
- return useRouterState({
49
- select: (state: any) =>
50
- opts?.select ? opts.select(state.location) : state.location,
51
- } as any) as UseLocationResult<TRouter, TSelected>
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,10 @@
1
1
  import * as React from 'react'
2
+ import { useStore } from '@tanstack/react-store'
3
+ import { replaceEqualDeep } from '@tanstack/router-core'
4
+ import { isServer } from '@tanstack/router-core/isServer'
2
5
  import invariant from 'tiny-invariant'
3
- import { useRouterState } from './useRouterState'
4
6
  import { dummyMatchContext, matchContext } from './matchContext'
7
+ import { useRouter } from './useRouter'
5
8
  import type {
6
9
  StructuralSharingOption,
7
10
  ValidateSelected,
@@ -16,6 +19,12 @@ import type {
16
19
  ThrowOrOptional,
17
20
  } from '@tanstack/router-core'
18
21
 
22
+ const dummyStore = {
23
+ state: undefined,
24
+ get: () => undefined,
25
+ subscribe: () => () => {},
26
+ } as any
27
+
19
28
  export interface UseMatchBaseOptions<
20
29
  TRouter extends AnyRouter,
21
30
  TFrom,
@@ -96,28 +105,59 @@ export function useMatch<
96
105
  TStructuralSharing
97
106
  >,
98
107
  ): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {
108
+ const router = useRouter<TRouter>()
99
109
  const nearestMatchId = React.useContext(
100
110
  opts.from ? dummyMatchContext : matchContext,
101
111
  )
102
112
 
103
- const matchSelection = useRouterState({
104
- select: (state: any) => {
105
- const match = state.matches.find((d: any) =>
106
- opts.from ? opts.from === d.routeId : d.id === nearestMatchId,
107
- )
108
- invariant(
109
- !((opts.shouldThrow ?? true) && !match),
110
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
111
- )
112
-
113
- if (match === undefined) {
114
- return undefined
115
- }
116
-
117
- return opts.select ? opts.select(match) : match
118
- },
119
- structuralSharing: opts.structuralSharing,
120
- } as any)
121
-
122
- return matchSelection as any
113
+ const key = opts.from ?? nearestMatchId
114
+ const matchStore = key
115
+ ? opts.from
116
+ ? router.stores.getMatchStoreByRouteId(key)
117
+ : router.stores.activeMatchStoresById.get(key)
118
+ : undefined
119
+
120
+ if (isServer ?? router.isServer) {
121
+ const match = matchStore?.state
122
+ invariant(
123
+ !((opts.shouldThrow ?? true) && !match),
124
+ `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
125
+ )
126
+
127
+ if (match === undefined) {
128
+ return undefined as any
129
+ }
130
+
131
+ return (opts.select ? opts.select(match as any) : match) as any
132
+ }
133
+
134
+ const previousResult =
135
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
136
+ React.useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(
137
+ undefined,
138
+ )
139
+
140
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
141
+ return useStore(matchStore ?? dummyStore, (match) => {
142
+ invariant(
143
+ !((opts.shouldThrow ?? true) && !match),
144
+ `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
145
+ )
146
+
147
+ if (match === undefined) {
148
+ return undefined
149
+ }
150
+
151
+ const selected = (
152
+ opts.select ? opts.select(match as any) : match
153
+ ) as ValidateSelected<TRouter, TSelected, TStructuralSharing>
154
+
155
+ if (opts.structuralSharing ?? router.options.defaultStructuralSharing) {
156
+ const shared = replaceEqualDeep(previousResult.current, selected)
157
+ previousResult.current = shared
158
+ return shared
159
+ }
160
+
161
+ return selected
162
+ }) as any
123
163
  }
@@ -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<TRouter['routeTree']>
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(