@tanstack/react-router 1.20.1 → 1.20.3-alpha.1

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 (320) hide show
  1. package/README.md +31 -0
  2. package/dist/cjs/Asset.cjs +41 -0
  3. package/dist/cjs/Asset.cjs.map +1 -0
  4. package/dist/cjs/Asset.d.cts +2 -0
  5. package/dist/cjs/CatchBoundary.cjs +16 -12
  6. package/dist/cjs/CatchBoundary.cjs.map +1 -1
  7. package/dist/cjs/CatchBoundary.d.cts +8 -32
  8. package/dist/cjs/ClientOnly.cjs +20 -0
  9. package/dist/cjs/ClientOnly.cjs.map +1 -0
  10. package/dist/cjs/ClientOnly.d.cts +29 -0
  11. package/dist/cjs/HeadContent.cjs +155 -0
  12. package/dist/cjs/HeadContent.cjs.map +1 -0
  13. package/dist/cjs/HeadContent.d.cts +7 -0
  14. package/dist/cjs/Match.cjs +252 -0
  15. package/dist/cjs/Match.cjs.map +1 -0
  16. package/dist/cjs/Match.d.cts +8 -0
  17. package/dist/cjs/Matches.cjs +39 -287
  18. package/dist/cjs/Matches.cjs.map +1 -1
  19. package/dist/cjs/Matches.d.cts +23 -83
  20. package/dist/cjs/RouterProvider.cjs +17 -140
  21. package/dist/cjs/RouterProvider.cjs.map +1 -1
  22. package/dist/cjs/RouterProvider.d.cts +8 -27
  23. package/dist/cjs/SafeFragment.cjs +8 -0
  24. package/dist/cjs/SafeFragment.cjs.map +1 -0
  25. package/dist/cjs/SafeFragment.d.cts +1 -0
  26. package/dist/cjs/ScriptOnce.cjs +28 -0
  27. package/dist/cjs/ScriptOnce.cjs.map +1 -0
  28. package/dist/cjs/ScriptOnce.d.cts +5 -0
  29. package/dist/cjs/Scripts.cjs +51 -0
  30. package/dist/cjs/Scripts.cjs.map +1 -0
  31. package/dist/cjs/Scripts.d.cts +1 -0
  32. package/dist/cjs/ScrollRestoration.cjs +39 -0
  33. package/dist/cjs/ScrollRestoration.cjs.map +1 -0
  34. package/dist/cjs/ScrollRestoration.d.cts +14 -0
  35. package/dist/cjs/Transitioner.cjs +115 -0
  36. package/dist/cjs/Transitioner.cjs.map +1 -0
  37. package/dist/cjs/Transitioner.d.cts +1 -0
  38. package/dist/cjs/awaited.cjs +12 -65
  39. package/dist/cjs/awaited.cjs.map +1 -1
  40. package/dist/cjs/awaited.d.cts +4 -4
  41. package/dist/cjs/fileRoute.cjs +41 -15
  42. package/dist/cjs/fileRoute.cjs.map +1 -1
  43. package/dist/cjs/fileRoute.d.cts +33 -108
  44. package/dist/cjs/history.d.cts +1 -0
  45. package/dist/cjs/index.cjs +216 -73
  46. package/dist/cjs/index.cjs.map +1 -1
  47. package/dist/cjs/index.d.cts +52 -29
  48. package/dist/cjs/lazyRouteComponent.cjs +40 -29
  49. package/dist/cjs/lazyRouteComponent.cjs.map +1 -1
  50. package/dist/cjs/lazyRouteComponent.d.cts +1 -1
  51. package/dist/cjs/link.cjs +212 -106
  52. package/dist/cjs/link.cjs.map +1 -1
  53. package/dist/cjs/link.d.cts +41 -86
  54. package/dist/cjs/matchContext.cjs +27 -0
  55. package/dist/cjs/matchContext.cjs.map +1 -0
  56. package/dist/cjs/matchContext.d.cts +3 -0
  57. package/dist/cjs/not-found.cjs +9 -15
  58. package/dist/cjs/not-found.cjs.map +1 -1
  59. package/dist/cjs/not-found.d.cts +5 -22
  60. package/dist/cjs/renderRouteNotFound.cjs +22 -0
  61. package/dist/cjs/renderRouteNotFound.cjs.map +1 -0
  62. package/dist/cjs/renderRouteNotFound.d.cts +2 -0
  63. package/dist/cjs/route.cjs +110 -79
  64. package/dist/cjs/route.cjs.map +1 -1
  65. package/dist/cjs/route.d.cts +64 -361
  66. package/dist/cjs/router.cjs +12 -1237
  67. package/dist/cjs/router.cjs.map +1 -1
  68. package/dist/cjs/router.d.cts +69 -237
  69. package/dist/cjs/routerContext.cjs +1 -1
  70. package/dist/cjs/routerContext.cjs.map +1 -1
  71. package/dist/cjs/routerContext.d.cts +7 -2
  72. package/dist/cjs/scroll-restoration.cjs +16 -177
  73. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  74. package/dist/cjs/scroll-restoration.d.cts +1 -18
  75. package/dist/cjs/serializer.d.cts +6 -0
  76. package/dist/cjs/structuralSharing.d.cts +8 -0
  77. package/dist/cjs/typePrimitives.d.cts +16 -0
  78. package/dist/cjs/useBlocker.cjs +138 -9
  79. package/dist/cjs/useBlocker.cjs.map +1 -1
  80. package/dist/cjs/useBlocker.d.cts +64 -7
  81. package/dist/cjs/useCanGoBack.cjs +8 -0
  82. package/dist/cjs/useCanGoBack.cjs.map +1 -0
  83. package/dist/cjs/useCanGoBack.d.cts +1 -0
  84. package/dist/cjs/useLoaderData.cjs +15 -0
  85. package/dist/cjs/useLoaderData.cjs.map +1 -0
  86. package/dist/cjs/useLoaderData.d.cts +8 -0
  87. package/dist/cjs/useLoaderDeps.cjs +14 -0
  88. package/dist/cjs/useLoaderDeps.cjs.map +1 -0
  89. package/dist/cjs/useLoaderDeps.d.cts +8 -0
  90. package/dist/cjs/useLocation.cjs +10 -0
  91. package/dist/cjs/useLocation.cjs.map +1 -0
  92. package/dist/cjs/useLocation.d.cts +7 -0
  93. package/dist/cjs/useMatch.cjs +47 -0
  94. package/dist/cjs/useMatch.cjs.map +1 -0
  95. package/dist/cjs/useMatch.d.cts +10 -0
  96. package/dist/cjs/useNavigate.cjs +18 -19
  97. package/dist/cjs/useNavigate.cjs.map +1 -1
  98. package/dist/cjs/useNavigate.d.cts +4 -8
  99. package/dist/cjs/useParams.cjs +8 -8
  100. package/dist/cjs/useParams.cjs.map +1 -1
  101. package/dist/cjs/useParams.d.cts +9 -8
  102. package/dist/cjs/useRouteContext.cjs +3 -3
  103. package/dist/cjs/useRouteContext.cjs.map +1 -1
  104. package/dist/cjs/useRouteContext.d.cts +3 -7
  105. package/dist/cjs/useRouter.cjs.map +1 -1
  106. package/dist/cjs/useRouter.d.cts +3 -4
  107. package/dist/cjs/useRouterState.cjs +18 -1
  108. package/dist/cjs/useRouterState.cjs.map +1 -1
  109. package/dist/cjs/useRouterState.d.cts +8 -6
  110. package/dist/cjs/useSearch.cjs +7 -4
  111. package/dist/cjs/useSearch.cjs.map +1 -1
  112. package/dist/cjs/useSearch.d.cts +9 -7
  113. package/dist/cjs/utils.cjs +40 -122
  114. package/dist/cjs/utils.cjs.map +1 -1
  115. package/dist/cjs/utils.d.cts +46 -50
  116. package/dist/esm/Asset.d.ts +2 -0
  117. package/dist/esm/Asset.js +41 -0
  118. package/dist/esm/Asset.js.map +1 -0
  119. package/dist/esm/CatchBoundary.d.ts +8 -32
  120. package/dist/esm/CatchBoundary.js +16 -12
  121. package/dist/esm/CatchBoundary.js.map +1 -1
  122. package/dist/esm/ClientOnly.d.ts +29 -0
  123. package/dist/esm/ClientOnly.js +20 -0
  124. package/dist/esm/ClientOnly.js.map +1 -0
  125. package/dist/esm/HeadContent.d.ts +7 -0
  126. package/dist/esm/HeadContent.js +139 -0
  127. package/dist/esm/HeadContent.js.map +1 -0
  128. package/dist/esm/Match.d.ts +8 -0
  129. package/dist/esm/Match.js +235 -0
  130. package/dist/esm/Match.js.map +1 -0
  131. package/dist/esm/Matches.d.ts +23 -83
  132. package/dist/esm/Matches.js +36 -284
  133. package/dist/esm/Matches.js.map +1 -1
  134. package/dist/esm/RouterProvider.d.ts +8 -27
  135. package/dist/esm/RouterProvider.js +20 -126
  136. package/dist/esm/RouterProvider.js.map +1 -1
  137. package/dist/esm/SafeFragment.d.ts +1 -0
  138. package/dist/esm/SafeFragment.js +8 -0
  139. package/dist/esm/SafeFragment.js.map +1 -0
  140. package/dist/esm/ScriptOnce.d.ts +5 -0
  141. package/dist/esm/ScriptOnce.js +28 -0
  142. package/dist/esm/ScriptOnce.js.map +1 -0
  143. package/dist/esm/Scripts.d.ts +1 -0
  144. package/dist/esm/Scripts.js +51 -0
  145. package/dist/esm/Scripts.js.map +1 -0
  146. package/dist/esm/ScrollRestoration.d.ts +14 -0
  147. package/dist/esm/ScrollRestoration.js +39 -0
  148. package/dist/esm/ScrollRestoration.js.map +1 -0
  149. package/dist/esm/Transitioner.d.ts +1 -0
  150. package/dist/esm/Transitioner.js +98 -0
  151. package/dist/esm/Transitioner.js.map +1 -0
  152. package/dist/esm/awaited.d.ts +4 -4
  153. package/dist/esm/awaited.js +12 -65
  154. package/dist/esm/awaited.js.map +1 -1
  155. package/dist/esm/fileRoute.d.ts +33 -108
  156. package/dist/esm/fileRoute.js +38 -12
  157. package/dist/esm/fileRoute.js.map +1 -1
  158. package/dist/esm/history.d.ts +1 -0
  159. package/dist/esm/index.d.ts +52 -29
  160. package/dist/esm/index.js +41 -29
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/lazyRouteComponent.d.ts +1 -1
  163. package/dist/esm/lazyRouteComponent.js +40 -29
  164. package/dist/esm/lazyRouteComponent.js.map +1 -1
  165. package/dist/esm/link.d.ts +41 -86
  166. package/dist/esm/link.js +212 -106
  167. package/dist/esm/link.js.map +1 -1
  168. package/dist/esm/matchContext.d.ts +3 -0
  169. package/dist/esm/matchContext.js +10 -0
  170. package/dist/esm/matchContext.js.map +1 -0
  171. package/dist/esm/not-found.d.ts +5 -22
  172. package/dist/esm/not-found.js +9 -15
  173. package/dist/esm/not-found.js.map +1 -1
  174. package/dist/esm/renderRouteNotFound.d.ts +2 -0
  175. package/dist/esm/renderRouteNotFound.js +22 -0
  176. package/dist/esm/renderRouteNotFound.js.map +1 -0
  177. package/dist/esm/route.d.ts +64 -361
  178. package/dist/esm/route.js +103 -72
  179. package/dist/esm/route.js.map +1 -1
  180. package/dist/esm/router.d.ts +69 -237
  181. package/dist/esm/router.js +13 -1238
  182. package/dist/esm/router.js.map +1 -1
  183. package/dist/esm/routerContext.d.ts +7 -2
  184. package/dist/esm/routerContext.js +1 -1
  185. package/dist/esm/routerContext.js.map +1 -1
  186. package/dist/esm/scroll-restoration.d.ts +1 -18
  187. package/dist/esm/scroll-restoration.js +17 -161
  188. package/dist/esm/scroll-restoration.js.map +1 -1
  189. package/dist/esm/serializer.d.ts +6 -0
  190. package/dist/esm/structuralSharing.d.ts +8 -0
  191. package/dist/esm/typePrimitives.d.ts +16 -0
  192. package/dist/esm/useBlocker.d.ts +64 -7
  193. package/dist/esm/useBlocker.js +138 -9
  194. package/dist/esm/useBlocker.js.map +1 -1
  195. package/dist/esm/useCanGoBack.d.ts +1 -0
  196. package/dist/esm/useCanGoBack.js +8 -0
  197. package/dist/esm/useCanGoBack.js.map +1 -0
  198. package/dist/esm/useLoaderData.d.ts +8 -0
  199. package/dist/esm/useLoaderData.js +15 -0
  200. package/dist/esm/useLoaderData.js.map +1 -0
  201. package/dist/esm/useLoaderDeps.d.ts +8 -0
  202. package/dist/esm/useLoaderDeps.js +14 -0
  203. package/dist/esm/useLoaderDeps.js.map +1 -0
  204. package/dist/esm/useLocation.d.ts +7 -0
  205. package/dist/esm/useLocation.js +10 -0
  206. package/dist/esm/useLocation.js.map +1 -0
  207. package/dist/esm/useMatch.d.ts +10 -0
  208. package/dist/esm/useMatch.js +30 -0
  209. package/dist/esm/useMatch.js.map +1 -0
  210. package/dist/esm/useNavigate.d.ts +4 -8
  211. package/dist/esm/useNavigate.js +18 -19
  212. package/dist/esm/useNavigate.js.map +1 -1
  213. package/dist/esm/useParams.d.ts +9 -8
  214. package/dist/esm/useParams.js +8 -8
  215. package/dist/esm/useParams.js.map +1 -1
  216. package/dist/esm/useRouteContext.d.ts +3 -7
  217. package/dist/esm/useRouteContext.js +2 -2
  218. package/dist/esm/useRouteContext.js.map +1 -1
  219. package/dist/esm/useRouter.d.ts +3 -4
  220. package/dist/esm/useRouter.js.map +1 -1
  221. package/dist/esm/useRouterState.d.ts +8 -6
  222. package/dist/esm/useRouterState.js +18 -1
  223. package/dist/esm/useRouterState.js.map +1 -1
  224. package/dist/esm/useSearch.d.ts +9 -7
  225. package/dist/esm/useSearch.js +6 -3
  226. package/dist/esm/useSearch.js.map +1 -1
  227. package/dist/esm/utils.d.ts +46 -50
  228. package/dist/esm/utils.js +41 -123
  229. package/dist/esm/utils.js.map +1 -1
  230. package/package.json +30 -31
  231. package/src/Asset.tsx +40 -0
  232. package/src/CatchBoundary.tsx +35 -19
  233. package/src/ClientOnly.tsx +68 -0
  234. package/src/HeadContent.tsx +174 -0
  235. package/src/Match.tsx +330 -0
  236. package/src/Matches.tsx +149 -558
  237. package/src/RouterProvider.tsx +58 -212
  238. package/src/SafeFragment.tsx +5 -0
  239. package/src/ScriptOnce.tsx +32 -0
  240. package/src/Scripts.tsx +65 -0
  241. package/src/ScrollRestoration.tsx +69 -0
  242. package/src/Transitioner.tsx +130 -0
  243. package/src/awaited.tsx +16 -87
  244. package/src/fileRoute.ts +145 -248
  245. package/src/history.ts +2 -1
  246. package/src/index.tsx +368 -30
  247. package/src/lazyRouteComponent.tsx +68 -54
  248. package/src/link.tsx +397 -522
  249. package/src/matchContext.tsx +8 -0
  250. package/src/not-found.tsx +13 -34
  251. package/src/renderRouteNotFound.tsx +27 -0
  252. package/src/route.tsx +572 -0
  253. package/src/router.ts +99 -2067
  254. package/src/routerContext.tsx +8 -2
  255. package/src/scroll-restoration.tsx +23 -224
  256. package/src/serializer.ts +7 -0
  257. package/src/structuralSharing.ts +47 -0
  258. package/src/typePrimitives.ts +84 -0
  259. package/src/useBlocker.tsx +297 -15
  260. package/src/useCanGoBack.ts +5 -0
  261. package/src/useLoaderData.tsx +80 -0
  262. package/src/useLoaderDeps.tsx +58 -0
  263. package/src/useLocation.tsx +41 -0
  264. package/src/useMatch.tsx +119 -0
  265. package/src/useNavigate.tsx +41 -61
  266. package/src/useParams.tsx +88 -23
  267. package/src/useRouteContext.ts +24 -18
  268. package/src/useRouter.tsx +4 -5
  269. package/src/useRouterState.tsx +52 -10
  270. package/src/useSearch.tsx +87 -24
  271. package/src/utils.ts +97 -312
  272. package/dist/cjs/createServerFn.cjs +0 -40
  273. package/dist/cjs/createServerFn.cjs.map +0 -1
  274. package/dist/cjs/createServerFn.d.cts +0 -44
  275. package/dist/cjs/defer.cjs +0 -30
  276. package/dist/cjs/defer.cjs.map +0 -1
  277. package/dist/cjs/defer.d.cts +0 -25
  278. package/dist/cjs/location.d.cts +0 -12
  279. package/dist/cjs/path.cjs +0 -213
  280. package/dist/cjs/path.cjs.map +0 -1
  281. package/dist/cjs/path.d.cts +0 -24
  282. package/dist/cjs/qss.cjs +0 -45
  283. package/dist/cjs/qss.cjs.map +0 -1
  284. package/dist/cjs/qss.d.cts +0 -2
  285. package/dist/cjs/redirects.cjs +0 -16
  286. package/dist/cjs/redirects.cjs.map +0 -1
  287. package/dist/cjs/redirects.d.cts +0 -18
  288. package/dist/cjs/routeInfo.d.cts +0 -31
  289. package/dist/cjs/searchParams.cjs +0 -63
  290. package/dist/cjs/searchParams.cjs.map +0 -1
  291. package/dist/cjs/searchParams.d.cts +0 -7
  292. package/dist/esm/createServerFn.d.ts +0 -44
  293. package/dist/esm/createServerFn.js +0 -40
  294. package/dist/esm/createServerFn.js.map +0 -1
  295. package/dist/esm/defer.d.ts +0 -25
  296. package/dist/esm/defer.js +0 -30
  297. package/dist/esm/defer.js.map +0 -1
  298. package/dist/esm/location.d.ts +0 -12
  299. package/dist/esm/path.d.ts +0 -24
  300. package/dist/esm/path.js +0 -213
  301. package/dist/esm/path.js.map +0 -1
  302. package/dist/esm/qss.d.ts +0 -2
  303. package/dist/esm/qss.js +0 -45
  304. package/dist/esm/qss.js.map +0 -1
  305. package/dist/esm/redirects.d.ts +0 -18
  306. package/dist/esm/redirects.js +0 -16
  307. package/dist/esm/redirects.js.map +0 -1
  308. package/dist/esm/routeInfo.d.ts +0 -31
  309. package/dist/esm/searchParams.d.ts +0 -7
  310. package/dist/esm/searchParams.js +0 -63
  311. package/dist/esm/searchParams.js.map +0 -1
  312. package/src/createServerFn.ts +0 -107
  313. package/src/defer.ts +0 -70
  314. package/src/location.ts +0 -13
  315. package/src/path.ts +0 -280
  316. package/src/qss.ts +0 -53
  317. package/src/redirects.ts +0 -56
  318. package/src/route.ts +0 -1356
  319. package/src/routeInfo.ts +0 -63
  320. package/src/searchParams.ts +0 -79
package/src/Matches.tsx CHANGED
@@ -1,105 +1,92 @@
1
1
  import * as React from 'react'
2
- import invariant from 'tiny-invariant'
3
2
  import warning from 'tiny-warning'
4
3
  import { CatchBoundary, ErrorComponent } from './CatchBoundary'
5
4
  import { useRouterState } from './useRouterState'
6
5
  import { useRouter } from './useRouter'
7
- import { ResolveRelativePath, ToOptions } from './link'
8
- import {
9
- AnyRoute,
10
- ReactNode,
11
- RootSearchSchema,
12
- StaticDataRouteOption,
13
- } from './route'
14
- import {
15
- AllParams,
16
- FullSearchSchema,
17
- ParseRoute,
18
- RouteById,
19
- RouteByPath,
20
- RouteIds,
21
- RoutePaths,
22
- } from './routeInfo'
23
- import { AnyRouter, RegisteredRouter, RouterState } from './router'
24
- import {
6
+ import { Transitioner } from './Transitioner'
7
+ import { matchContext } from './matchContext'
8
+ import { Match } from './Match'
9
+ import { SafeFragment } from './SafeFragment'
10
+ import type {
11
+ StructuralSharingOption,
12
+ ValidateSelected,
13
+ } from './structuralSharing'
14
+ import type { ReactNode } from './route'
15
+ import type {
16
+ AnyRouter,
25
17
  DeepPartial,
26
- Expand,
18
+ MakeOptionalPathParams,
19
+ MakeOptionalSearchParams,
20
+ MakeRouteMatchUnion,
21
+ MaskOptions,
22
+ MatchRouteOptions,
27
23
  NoInfer,
28
- StrictOrFrom,
29
- isServer,
30
- pick,
31
- } from './utils'
32
- import { CatchNotFound, DefaultGlobalNotFound, isNotFound } from './not-found'
33
- import { isRedirect } from './redirects'
34
-
35
- export const matchContext = React.createContext<string | undefined>(undefined)
36
-
37
- export interface RouteMatch<
38
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
39
- TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
40
- TReturnIntersection extends boolean = false,
41
- > {
42
- id: string
43
- routeId: TRouteId
44
- pathname: string
45
- params: TReturnIntersection extends false
46
- ? RouteById<TRouteTree, TRouteId>['types']['allParams']
47
- : Expand<Partial<AllParams<TRouteTree>>>
48
- status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'
49
- isFetching: boolean
50
- showPending: boolean
51
- error: unknown
52
- paramsError: unknown
53
- searchError: unknown
54
- updatedAt: number
55
- loadPromise?: Promise<void>
56
- loaderData?: RouteById<TRouteTree, TRouteId>['types']['loaderData']
57
- routeContext: RouteById<TRouteTree, TRouteId>['types']['routeContext']
58
- context: RouteById<TRouteTree, TRouteId>['types']['allContext']
59
- search: TReturnIntersection extends false
60
- ? Exclude<
61
- RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'],
62
- RootSearchSchema
63
- >
64
- : Expand<
65
- Partial<Omit<FullSearchSchema<TRouteTree>, keyof RootSearchSchema>>
66
- >
67
- fetchCount: number
68
- abortController: AbortController
69
- cause: 'preload' | 'enter' | 'stay'
70
- loaderDeps: RouteById<TRouteTree, TRouteId>['types']['loaderDeps']
71
- preload: boolean
72
- invalid: boolean
73
- pendingPromise?: Promise<void>
74
- meta?: JSX.IntrinsicElements['meta'][]
75
- links?: JSX.IntrinsicElements['link'][]
76
- scripts?: JSX.IntrinsicElements['script'][]
77
- headers?: Record<string, string>
78
- globalNotFound?: boolean
79
- staticData: StaticDataRouteOption
24
+ RegisteredRouter,
25
+ ResolveRelativePath,
26
+ ResolveRoute,
27
+ RouteByPath,
28
+ RouterState,
29
+ ToSubOptionsProps,
30
+ } from '@tanstack/router-core'
31
+
32
+ declare module '@tanstack/router-core' {
33
+ export interface RouteMatchExtensions {
34
+ meta?: Array<React.JSX.IntrinsicElements['meta'] | undefined>
35
+ links?: Array<React.JSX.IntrinsicElements['link'] | undefined>
36
+ scripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>
37
+ headScripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>
38
+ }
80
39
  }
81
40
 
82
- export type AnyRouteMatch = RouteMatch<any, any>
83
-
84
41
  export function Matches() {
85
42
  const router = useRouter()
43
+
44
+ const pendingElement = router.options.defaultPendingComponent ? (
45
+ <router.options.defaultPendingComponent />
46
+ ) : null
47
+
48
+ // Do not render a root Suspense during SSR or hydrating from SSR
49
+ const ResolvedSuspense =
50
+ router.isServer || (typeof document !== 'undefined' && router.clientSsr)
51
+ ? SafeFragment
52
+ : React.Suspense
53
+
54
+ const inner = (
55
+ <ResolvedSuspense fallback={pendingElement}>
56
+ <Transitioner />
57
+ <MatchesInner />
58
+ </ResolvedSuspense>
59
+ )
60
+
61
+ return router.options.InnerWrap ? (
62
+ <router.options.InnerWrap>{inner}</router.options.InnerWrap>
63
+ ) : (
64
+ inner
65
+ )
66
+ }
67
+
68
+ function MatchesInner() {
86
69
  const matchId = useRouterState({
87
70
  select: (s) => {
88
- return getRenderedMatches(s)[0]?.id
71
+ return s.matches[0]?.id
89
72
  },
90
73
  })
91
74
 
75
+ const resetKey = useRouterState({
76
+ select: (s) => s.loadedAt,
77
+ })
78
+
92
79
  return (
93
80
  <matchContext.Provider value={matchId}>
94
81
  <CatchBoundary
95
- getResetKey={() => router.state.resolvedLocation.state?.key!}
82
+ getResetKey={() => resetKey}
96
83
  errorComponent={ErrorComponent}
97
84
  onCatch={(error) => {
98
85
  warning(
99
86
  false,
100
- `The following error wasn't caught by any route! 👇 At the very least, consider setting an 'errorComponent' in your RootRoute!`,
87
+ `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
101
88
  )
102
- console.error(error)
89
+ warning(false, error.message || error.toString())
103
90
  }}
104
91
  >
105
92
  {matchId ? <Match matchId={matchId} /> : null}
@@ -108,326 +95,60 @@ export function Matches() {
108
95
  )
109
96
  }
110
97
 
111
- function SafeFragment(props: any) {
112
- return <>{props.children}</>
113
- }
114
-
115
- export function Match({ matchId }: { matchId: string }) {
116
- const router = useRouter()
117
- const routeId = useRouterState({
118
- select: (s) =>
119
- getRenderedMatches(s).find((d) => d.id === matchId)?.routeId as string,
120
- })
121
-
122
- invariant(
123
- routeId,
124
- `Could not find routeId for matchId "${matchId}". Please file an issue!`,
125
- )
126
-
127
- const route = router.routesById[routeId]!
128
-
129
- const PendingComponent = (route.options.pendingComponent ??
130
- router.options.defaultPendingComponent) as any
131
-
132
- const pendingElement = PendingComponent ? <PendingComponent /> : null
133
-
134
- const routeErrorComponent =
135
- route.options.errorComponent ??
136
- router.options.defaultErrorComponent ??
137
- ErrorComponent
138
-
139
- const routeNotFoundComponent = route.isRoot
140
- ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component
141
- route.options.notFoundComponent ??
142
- router.options.notFoundRoute?.options.component
143
- : route.options.notFoundComponent
144
-
145
- const ResolvedSuspenseBoundary =
146
- route.options.wrapInSuspense ??
147
- PendingComponent ??
148
- route.options.component?.preload ??
149
- route.options.pendingComponent?.preload ??
150
- (route.options.errorComponent as any)?.preload
151
- ? React.Suspense
152
- : SafeFragment
153
-
154
- const ResolvedCatchBoundary = routeErrorComponent
155
- ? CatchBoundary
156
- : SafeFragment
157
-
158
- const ResolvedNotFoundBoundary = routeNotFoundComponent
159
- ? CatchNotFound
160
- : SafeFragment
161
-
162
- return (
163
- <matchContext.Provider value={matchId}>
164
- <ResolvedSuspenseBoundary fallback={pendingElement}>
165
- <ResolvedCatchBoundary
166
- getResetKey={() => router.state.resolvedLocation.state?.key!}
167
- errorComponent={routeErrorComponent}
168
- onCatch={(error) => {
169
- // Forward not found errors (we don't want to show the error component for these)
170
- if (isNotFound(error)) throw error
171
- warning(false, `Error in route match: ${matchId}`)
172
- console.error(error)
173
- }}
174
- >
175
- <ResolvedNotFoundBoundary
176
- fallback={(error) => {
177
- // If the current not found handler doesn't exist or it has a
178
- // route ID which doesn't match the current route, rethrow the error
179
- if (
180
- !routeNotFoundComponent ||
181
- (error.routeId && error.routeId !== routeId) ||
182
- (!error.routeId && !route.isRoot)
183
- )
184
- throw error
185
-
186
- return React.createElement(routeNotFoundComponent, error as any)
187
- }}
188
- >
189
- <MatchInner matchId={matchId!} pendingElement={pendingElement} />
190
- </ResolvedNotFoundBoundary>
191
- </ResolvedCatchBoundary>
192
- </ResolvedSuspenseBoundary>
193
- </matchContext.Provider>
194
- )
195
- }
98
+ export type UseMatchRouteOptions<
99
+ TRouter extends AnyRouter = RegisteredRouter,
100
+ TFrom extends string = string,
101
+ TTo extends string | undefined = undefined,
102
+ TMaskFrom extends string = TFrom,
103
+ TMaskTo extends string = '',
104
+ > = ToSubOptionsProps<TRouter, TFrom, TTo> &
105
+ DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> &
106
+ DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> &
107
+ MaskOptions<TRouter, TMaskFrom, TMaskTo> &
108
+ MatchRouteOptions
196
109
 
197
- function MatchInner({
198
- matchId,
199
- pendingElement,
200
- }: {
201
- matchId: string
202
- pendingElement: any
203
- }): any {
110
+ export function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {
204
111
  const router = useRouter()
205
- const routeId = useRouterState({
206
- select: (s) =>
207
- getRenderedMatches(s).find((d) => d.id === matchId)?.routeId as string,
208
- })
209
112
 
210
- const route = router.routesById[routeId]!
211
-
212
- const match = useRouterState({
213
- select: (s) =>
214
- pick(getRenderedMatches(s).find((d) => d.id === matchId)!, [
215
- 'status',
216
- 'error',
217
- 'showPending',
218
- 'loadPromise',
219
- ]),
113
+ useRouterState({
114
+ select: (s) => [s.location.href, s.resolvedLocation?.href, s.status],
115
+ structuralSharing: true as any,
220
116
  })
221
117
 
222
- const RouteErrorComponent =
223
- (route.options.errorComponent ?? router.options.defaultErrorComponent) ||
224
- ErrorComponent
225
-
226
- if (match.status === 'notFound') {
227
- let error: unknown
228
- if (isServerSideError(match.error)) {
229
- const deserializeError =
230
- router.options.errorSerializer?.deserialize ?? defaultDeserializeError
231
-
232
- error = deserializeError(match.error.data)
233
- } else {
234
- error = match.error
235
- }
236
-
237
- invariant(isNotFound(error), 'Expected a notFound error')
238
-
239
- return renderRouteNotFound(router, route, error)
240
- }
241
-
242
- if (match.status === 'redirected') {
243
- // Redirects should be handled by the router transition. If we happen to
244
- // encounter a redirect here, it's a bug. Let's warn, but render nothing.
245
- invariant(isRedirect(match.error), 'Expected a redirect error')
246
-
247
- warning(
248
- false,
249
- 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',
250
- )
251
-
252
- return null
253
- }
254
-
255
- if (match.status === 'error') {
256
- // If we're on the server, we need to use React's new and super
257
- // wonky api for throwing errors from a server side render inside
258
- // of a suspense boundary. This is the only way to get
259
- // renderToPipeableStream to not hang indefinitely.
260
- // We'll serialize the error and rethrow it on the client.
261
- if (isServer) {
262
- return (
263
- <RouteErrorComponent
264
- error={match.error}
265
- info={{
266
- componentStack: '',
267
- }}
268
- />
269
- )
270
- }
271
-
272
- if (isServerSideError(match.error)) {
273
- const deserializeError =
274
- router.options.errorSerializer?.deserialize ?? defaultDeserializeError
275
- throw deserializeError(match.error.data)
276
- } else {
277
- throw match.error
278
- }
279
- }
280
-
281
- if (match.status === 'pending') {
282
- if (match.showPending) {
283
- return pendingElement
284
- }
285
- throw match.loadPromise
286
- }
287
-
288
- if (match.status === 'success') {
289
- let Comp = route.options.component ?? router.options.defaultComponent
290
-
291
- if (Comp) {
292
- return <Comp />
293
- }
294
-
295
- return <Outlet />
296
- }
297
-
298
- invariant(
299
- false,
300
- 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!',
301
- )
302
- }
303
-
304
- export const Outlet = React.memo(function Outlet() {
305
- const router = useRouter()
306
- const matchId = React.useContext(matchContext)
307
- const routeId = useRouterState({
308
- select: (s) =>
309
- getRenderedMatches(s).find((d) => d.id === matchId)?.routeId as string,
310
- })
311
-
312
- const route = router.routesById[routeId]!
313
-
314
- const { parentGlobalNotFound } = useRouterState({
315
- select: (s) => {
316
- const matches = getRenderedMatches(s)
317
- const parentMatch = matches.find((d) => d.id === matchId)
318
- invariant(
319
- parentMatch,
320
- `Could not find parent match for matchId "${matchId}"`,
321
- )
322
- return {
323
- parentGlobalNotFound: parentMatch.globalNotFound,
324
- }
325
- },
326
- })
327
-
328
- const childMatchId = useRouterState({
329
- select: (s) => {
330
- const matches = getRenderedMatches(s)
331
- const index = matches.findIndex((d) => d.id === matchId)
332
- return matches[index + 1]?.id
333
- },
334
- })
335
-
336
- if (parentGlobalNotFound) {
337
- return renderRouteNotFound(router, route, undefined)
338
- }
339
-
340
- if (!childMatchId) {
341
- return null
342
- }
343
-
344
- return <Match matchId={childMatchId} />
345
- })
346
-
347
- function renderRouteNotFound(router: AnyRouter, route: AnyRoute, data: any) {
348
- if (!route.options.notFoundComponent) {
349
- if (router.options.defaultNotFoundComponent) {
350
- return <router.options.defaultNotFoundComponent data={data} />
351
- }
352
-
353
- if (process.env.NODE_ENV === 'development') {
354
- warning(
355
- route.options.notFoundComponent,
356
- `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 (<div>Not Found<div>)`,
357
- )
358
- }
359
-
360
- return <DefaultGlobalNotFound />
361
- }
362
-
363
- return <route.options.notFoundComponent data={data} />
364
- }
365
-
366
- export interface MatchRouteOptions {
367
- pending?: boolean
368
- caseSensitive?: boolean
369
- includeSearch?: boolean
370
- fuzzy?: boolean
371
- }
372
-
373
- export type UseMatchRouteOptions<
374
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
375
- TFrom extends RoutePaths<TRouteTree> = RoutePaths<TRouteTree>,
376
- TTo extends string = '',
377
- TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
378
- TMaskTo extends string = '',
379
- Options extends ToOptions<
380
- TRouteTree,
381
- TFrom,
382
- TTo,
383
- TMaskFrom,
384
- TMaskTo
385
- > = ToOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
386
- RelaxedOptions = Omit<Options, 'search' | 'params'> &
387
- DeepPartial<Pick<Options, 'search' | 'params'>>,
388
- > = RelaxedOptions & MatchRouteOptions
389
-
390
- export function useMatchRoute<
391
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
392
- >() {
393
- useRouterState({ select: (s) => [s.location, s.resolvedLocation] })
394
- const { matchRoute } = useRouter()
395
-
396
118
  return React.useCallback(
397
119
  <
398
- TFrom extends RoutePaths<TRouteTree> = RoutePaths<TRouteTree>,
399
- TTo extends string = '',
400
- TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
401
- TMaskTo extends string = '',
402
- TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>,
120
+ const TFrom extends string = string,
121
+ const TTo extends string | undefined = undefined,
122
+ const TMaskFrom extends string = TFrom,
123
+ const TMaskTo extends string = '',
403
124
  >(
404
- opts: UseMatchRouteOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
405
- ): false | RouteById<TRouteTree, TResolved>['types']['allParams'] => {
125
+ opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
126
+ ): false | ResolveRoute<TRouter, TFrom, TTo>['types']['allParams'] => {
406
127
  const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts
407
128
 
408
- return matchRoute(rest as any, {
129
+ return router.matchRoute(rest as any, {
409
130
  pending,
410
131
  caseSensitive,
411
132
  fuzzy,
412
133
  includeSearch,
413
134
  })
414
135
  },
415
- [],
136
+ [router],
416
137
  )
417
138
  }
418
139
 
419
140
  export type MakeMatchRouteOptions<
420
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
421
- TFrom extends RoutePaths<TRouteTree> = RoutePaths<TRouteTree>,
422
- TTo extends string = '',
423
- TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
141
+ TRouter extends AnyRouter = RegisteredRouter,
142
+ TFrom extends string = string,
143
+ TTo extends string | undefined = undefined,
144
+ TMaskFrom extends string = TFrom,
424
145
  TMaskTo extends string = '',
425
- > = UseMatchRouteOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
146
+ > = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {
426
147
  // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
427
148
  children?:
428
149
  | ((
429
150
  params?: RouteByPath<
430
- TRouteTree,
151
+ TRouter['routeTree'],
431
152
  ResolveRelativePath<TFrom, NoInfer<TTo>>
432
153
  >['types']['allParams'],
433
154
  ) => ReactNode)
@@ -435,225 +156,95 @@ export type MakeMatchRouteOptions<
435
156
  }
436
157
 
437
158
  export function MatchRoute<
438
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
439
- TFrom extends RoutePaths<TRouteTree> = RoutePaths<TRouteTree>,
440
- TTo extends string = '',
441
- TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
442
- TMaskTo extends string = '',
443
- >(
444
- props: MakeMatchRouteOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
445
- ): any {
159
+ TRouter extends AnyRouter = RegisteredRouter,
160
+ const TFrom extends string = string,
161
+ const TTo extends string | undefined = undefined,
162
+ const TMaskFrom extends string = TFrom,
163
+ const TMaskTo extends string = '',
164
+ >(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {
446
165
  const matchRoute = useMatchRoute()
447
- const params = matchRoute(props as any)
166
+ const params = matchRoute(props as any) as boolean
448
167
 
449
168
  if (typeof props.children === 'function') {
450
169
  return (props.children as any)(params)
451
170
  }
452
171
 
453
- return !!params ? props.children : null
172
+ return params ? props.children : null
454
173
  }
455
174
 
456
- export function getRenderedMatches<
457
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
458
- >(state: RouterState<TRouteTree>) {
459
- return state.pendingMatches?.some((d) => d.showPending)
460
- ? state.pendingMatches
461
- : state.matches
175
+ export interface UseMatchesBaseOptions<
176
+ TRouter extends AnyRouter,
177
+ TSelected,
178
+ TStructuralSharing,
179
+ > {
180
+ select?: (
181
+ matches: Array<MakeRouteMatchUnion<TRouter>>,
182
+ ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>
462
183
  }
463
184
 
464
- export function useMatch<
465
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
466
- TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
467
- TReturnIntersection extends boolean = false,
468
- TRouteMatchState = RouteMatch<TRouteTree, TFrom, TReturnIntersection>,
469
- TSelected = TRouteMatchState,
470
- >(
471
- opts: StrictOrFrom<TFrom, TReturnIntersection> & {
472
- select?: (match: TRouteMatchState) => TSelected
473
- },
474
- ): TSelected {
475
- const router = useRouter()
476
- const nearestMatchId = React.useContext(matchContext)
477
-
478
- const nearestMatchRouteId = getRenderedMatches(router.state).find(
479
- (d) => d.id === nearestMatchId,
480
- )?.routeId
481
-
482
- const matchRouteId = (() => {
483
- const matches = getRenderedMatches(router.state)
484
- const match = opts?.from
485
- ? matches.find((d) => d.routeId === opts?.from)
486
- : matches.find((d) => d.id === nearestMatchId)
487
- return match!.routeId
488
- })()
489
-
490
- if (opts?.strict ?? true) {
491
- invariant(
492
- nearestMatchRouteId == matchRouteId,
493
- `useMatch("${
494
- matchRouteId as string
495
- }") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${
496
- matchRouteId as string
497
- }", { strict: false })' or 'useRoute("${
498
- matchRouteId as string
499
- }")' instead?`,
500
- )
501
- }
502
-
503
- const matchSelection = useRouterState({
504
- select: (state) => {
505
- const match = getRenderedMatches(state).find((d) =>
506
- opts?.from ? opts?.from === d.routeId : d.id === nearestMatchId,
507
- )
508
-
509
- invariant(
510
- match,
511
- `Could not find ${
512
- opts?.from
513
- ? `an active match from "${opts.from}"`
514
- : 'a nearest match!'
515
- }`,
516
- )
517
-
518
- return opts?.select ? opts.select(match as any) : match
519
- },
520
- })
521
-
522
- return matchSelection as any
523
- }
185
+ export type UseMatchesResult<
186
+ TRouter extends AnyRouter,
187
+ TSelected,
188
+ > = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected
524
189
 
525
190
  export function useMatches<
526
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
527
- TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
528
- TReturnIntersection extends boolean = false,
529
- TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
530
- T = TRouteMatch[],
531
- >(opts?: {
532
- select?: (matches: TRouteMatch[]) => T
533
- experimental_returnIntersection?: TReturnIntersection
534
- }): T {
191
+ TRouter extends AnyRouter = RegisteredRouter,
192
+ TSelected = unknown,
193
+ TStructuralSharing extends boolean = boolean,
194
+ >(
195
+ opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &
196
+ StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,
197
+ ): UseMatchesResult<TRouter, TSelected> {
535
198
  return useRouterState({
536
- select: (state) => {
537
- const matches = getRenderedMatches(state)
199
+ select: (state: RouterState<TRouter['routeTree']>) => {
200
+ const matches = state.matches
538
201
  return opts?.select
539
- ? opts.select(matches as TRouteMatch[])
540
- : (matches as T)
202
+ ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)
203
+ : matches
541
204
  },
542
- })
205
+ structuralSharing: opts?.structuralSharing,
206
+ } as any) as UseMatchesResult<TRouter, TSelected>
543
207
  }
544
208
 
545
209
  export function useParentMatches<
546
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
547
- TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
548
- TReturnIntersection extends boolean = false,
549
- TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
550
- T = TRouteMatch[],
551
- >(opts?: {
552
- select?: (matches: TRouteMatch[]) => T
553
- experimental_returnIntersection?: TReturnIntersection
554
- }): T {
210
+ TRouter extends AnyRouter = RegisteredRouter,
211
+ TSelected = unknown,
212
+ TStructuralSharing extends boolean = boolean,
213
+ >(
214
+ opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &
215
+ StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,
216
+ ): UseMatchesResult<TRouter, TSelected> {
555
217
  const contextMatchId = React.useContext(matchContext)
556
218
 
557
219
  return useMatches({
558
- select: (matches) => {
220
+ select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
559
221
  matches = matches.slice(
560
222
  0,
561
223
  matches.findIndex((d) => d.id === contextMatchId),
562
224
  )
563
- return opts?.select
564
- ? opts.select(matches as TRouteMatch[])
565
- : (matches as T)
225
+ return opts?.select ? opts.select(matches) : matches
566
226
  },
567
- })
227
+ structuralSharing: opts?.structuralSharing,
228
+ } as any)
568
229
  }
569
230
 
570
231
  export function useChildMatches<
571
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
572
- TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
573
- TReturnIntersection extends boolean = false,
574
- TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
575
- T = TRouteMatch[],
576
- >(opts?: {
577
- select?: (matches: TRouteMatch[]) => T
578
- experimental_returnIntersection?: TReturnIntersection
579
- }): T {
232
+ TRouter extends AnyRouter = RegisteredRouter,
233
+ TSelected = unknown,
234
+ TStructuralSharing extends boolean = boolean,
235
+ >(
236
+ opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &
237
+ StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,
238
+ ): UseMatchesResult<TRouter, TSelected> {
580
239
  const contextMatchId = React.useContext(matchContext)
581
240
 
582
241
  return useMatches({
583
- select: (matches) => {
242
+ select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
584
243
  matches = matches.slice(
585
244
  matches.findIndex((d) => d.id === contextMatchId) + 1,
586
245
  )
587
- return opts?.select
588
- ? opts.select(matches as TRouteMatch[])
589
- : (matches as T)
246
+ return opts?.select ? opts.select(matches) : matches
590
247
  },
591
- })
592
- }
593
-
594
- export function useLoaderDeps<
595
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
596
- TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
597
- TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
598
- TRouteTree,
599
- TFrom
600
- >,
601
- TSelected = Required<TRouteMatch>['loaderDeps'],
602
- >(
603
- opts: StrictOrFrom<TFrom> & {
604
- select?: (match: TRouteMatch) => TSelected
605
- },
606
- ): TSelected {
607
- return useMatch({
608
- ...opts,
609
- select: (s) => {
610
- return typeof opts.select === 'function'
611
- ? opts.select(s?.loaderDeps)
612
- : s?.loaderDeps
613
- },
614
- })
615
- }
616
-
617
- export function useLoaderData<
618
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
619
- TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
620
- TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
621
- TRouteTree,
622
- TFrom
623
- >,
624
- TSelected = Required<TRouteMatch>['loaderData'],
625
- >(
626
- opts: StrictOrFrom<TFrom> & {
627
- select?: (match: TRouteMatch) => TSelected
628
- },
629
- ): TSelected {
630
- return useMatch({
631
- ...opts,
632
- select: (s) => {
633
- return typeof opts.select === 'function'
634
- ? opts.select(s?.loaderData)
635
- : s?.loaderData
636
- },
637
- })
638
- }
639
-
640
- export function isServerSideError(error: unknown): error is {
641
- __isServerError: true
642
- data: Record<string, any>
643
- } {
644
- if (!(typeof error === 'object' && error && 'data' in error)) return false
645
- if (!('__isServerError' in error && error.__isServerError)) return false
646
- if (!(typeof error.data === 'object' && error.data)) return false
647
-
648
- return error.__isServerError === true
649
- }
650
-
651
- export function defaultDeserializeError(serializedData: Record<string, any>) {
652
- if ('name' in serializedData && 'message' in serializedData) {
653
- const error = new Error(serializedData.message)
654
- error.name = serializedData.name
655
- return error
656
- }
657
-
658
- return serializedData.data
248
+ structuralSharing: opts?.structuralSharing,
249
+ } as any)
659
250
  }