@tanstack/react-router 1.168.1 → 1.168.2
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/cjs/Match.cjs +37 -14
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +2 -4
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/fileRoute.cjs +4 -6
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/renderRouteNotFound.cjs +3 -3
- package/dist/cjs/renderRouteNotFound.cjs.map +1 -1
- package/dist/cjs/route.cjs +0 -2
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/useMatch.cjs +8 -4
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/useRouter.cjs +3 -3
- package/dist/cjs/useRouter.cjs.map +1 -1
- package/dist/esm/Match.js +38 -13
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +2 -3
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/fileRoute.js +4 -4
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/renderRouteNotFound.js +3 -2
- package/dist/esm/renderRouteNotFound.js.map +1 -1
- package/dist/esm/route.js +0 -2
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/useMatch.js +9 -4
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useRouter.js +3 -2
- package/dist/esm/useRouter.js.map +1 -1
- package/dist/llms/rules/api.d.ts +1 -1
- package/dist/llms/rules/api.js +10 -10
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +27 -6
- package/package.json +2 -4
- package/src/Match.tsx +77 -24
- package/src/Matches.tsx +3 -5
- package/src/fileRoute.ts +7 -9
- package/src/renderRouteNotFound.tsx +6 -6
- package/src/route.tsx +0 -2
- package/src/useMatch.tsx +19 -10
- package/src/useRouter.tsx +7 -5
package/dist/llms/rules/guide.js
CHANGED
|
@@ -8384,7 +8384,9 @@ For validation libraries we recommend using adapters which infer the correct \`i
|
|
|
8384
8384
|
|
|
8385
8385
|
### Zod
|
|
8386
8386
|
|
|
8387
|
-
An adapter is provided for [Zod](https://zod.dev/) which will pipe through the correct \`input\` type and \`output\` type
|
|
8387
|
+
An adapter is provided for [Zod](https://zod.dev/) which will pipe through the correct \`input\` type and \`output\` type.
|
|
8388
|
+
|
|
8389
|
+
For Zod v3:
|
|
8388
8390
|
|
|
8389
8391
|
\`\`\`tsx
|
|
8390
8392
|
import { zodValidator } from '@tanstack/zod-adapter'
|
|
@@ -8401,13 +8403,30 @@ export const Route = createFileRoute('/shop/products/')({
|
|
|
8401
8403
|
})
|
|
8402
8404
|
\`\`\`
|
|
8403
8405
|
|
|
8404
|
-
|
|
8406
|
+
With Zod v4, you should directly use the schema in \`validateSearch\`:
|
|
8407
|
+
|
|
8408
|
+
\`\`\`tsx
|
|
8409
|
+
import { z } from 'zod'
|
|
8410
|
+
|
|
8411
|
+
const productSearchSchema = z.object({
|
|
8412
|
+
page: z.number().default(1),
|
|
8413
|
+
filter: z.string().default(''),
|
|
8414
|
+
sort: z.enum(['newest', 'oldest', 'price']).default('newest'),
|
|
8415
|
+
})
|
|
8416
|
+
|
|
8417
|
+
export const Route = createFileRoute('/shop/products/')({
|
|
8418
|
+
// With Zod v4, we can use the schema without the adapter
|
|
8419
|
+
validateSearch: productSearchSchema,
|
|
8420
|
+
})
|
|
8421
|
+
\`\`\`
|
|
8422
|
+
|
|
8423
|
+
The important part here is the following use of \`Link\` no longer requires \`search\` params:
|
|
8405
8424
|
|
|
8406
8425
|
\`\`\`tsx
|
|
8407
8426
|
<Link to="/shop/products" />
|
|
8408
8427
|
\`\`\`
|
|
8409
8428
|
|
|
8410
|
-
|
|
8429
|
+
In Zod v3, the use of \`catch\` here overrides the types and makes \`page\`, \`filter\` and \`sort\` \`unknown\` causing type loss. We have handled this case by providing a \`fallback\` generic function which retains the types but provides a \`fallback\` value when validation fails:
|
|
8411
8430
|
|
|
8412
8431
|
\`\`\`tsx
|
|
8413
8432
|
import { fallback, zodValidator } from '@tanstack/zod-adapter'
|
|
@@ -8428,7 +8447,9 @@ export const Route = createFileRoute('/shop/products/')({
|
|
|
8428
8447
|
|
|
8429
8448
|
Therefore when navigating to this route, \`search\` is optional and retains the correct types.
|
|
8430
8449
|
|
|
8431
|
-
|
|
8450
|
+
In Zod v4, schemas may use \`catch\` instead of the fallback and will retain type inference throughout.
|
|
8451
|
+
|
|
8452
|
+
While not recommended, it is also possible to configure \`input\` and \`output\` type in case the \`output\` type is more accurate than the \`input\` type:
|
|
8432
8453
|
|
|
8433
8454
|
\`\`\`tsx
|
|
8434
8455
|
const productSearchSchema = z.object({
|
|
@@ -8645,7 +8666,7 @@ Now that you've learned how to read your route's search params, you'll be happy
|
|
|
8645
8666
|
|
|
8646
8667
|
The best way to update search params is to use the \`search\` prop on the \`<Link />\` component.
|
|
8647
8668
|
|
|
8648
|
-
If the search for the current page shall be updated and the \`from\` prop is specified, the \`to\` prop can be omitted.
|
|
8669
|
+
If the search for the current page shall be updated and the \`from\` prop is specified, the \`to\` prop can be omitted.
|
|
8649
8670
|
Here's an example:
|
|
8650
8671
|
|
|
8651
8672
|
\`\`\`tsx title="src/routes/shop/products.tsx"
|
|
@@ -8666,7 +8687,7 @@ const ProductList = () => {
|
|
|
8666
8687
|
|
|
8667
8688
|
If you want to update the search params in a generic component that is rendered on multiple routes, specifying \`from\` can be challenging.
|
|
8668
8689
|
|
|
8669
|
-
In this scenario you can set \`to="."\` which will give you access to loosely typed search params.
|
|
8690
|
+
In this scenario you can set \`to="."\` which will give you access to loosely typed search params.
|
|
8670
8691
|
Here is an example that illustrates this:
|
|
8671
8692
|
|
|
8672
8693
|
\`\`\`tsx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.168.
|
|
3
|
+
"version": "1.168.2",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -79,10 +79,8 @@
|
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@tanstack/react-store": "^0.9.2",
|
|
81
81
|
"isbot": "^5.1.22",
|
|
82
|
-
"tiny-invariant": "^1.3.3",
|
|
83
|
-
"tiny-warning": "^1.0.3",
|
|
84
82
|
"@tanstack/history": "1.161.6",
|
|
85
|
-
"@tanstack/router-core": "1.168.
|
|
83
|
+
"@tanstack/router-core": "1.168.2"
|
|
86
84
|
},
|
|
87
85
|
"devDependencies": {
|
|
88
86
|
"@testing-library/jest-dom": "^6.6.3",
|
package/src/Match.tsx
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { useStore } from '@tanstack/react-store'
|
|
3
|
-
import invariant from 'tiny-invariant'
|
|
4
|
-
import warning from 'tiny-warning'
|
|
5
3
|
import {
|
|
6
4
|
createControlledPromise,
|
|
7
5
|
getLocationChangeInfo,
|
|
6
|
+
invariant,
|
|
8
7
|
isNotFound,
|
|
9
8
|
isRedirect,
|
|
10
9
|
rootRouteId,
|
|
@@ -33,10 +32,15 @@ export const Match = React.memo(function MatchImpl({
|
|
|
33
32
|
|
|
34
33
|
if (isServer ?? router.isServer) {
|
|
35
34
|
const match = router.stores.activeMatchStoresById.get(matchId)?.state
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (!match) {
|
|
36
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
invariant()
|
|
43
|
+
}
|
|
40
44
|
|
|
41
45
|
const routeId = match.routeId as string
|
|
42
46
|
const parentRouteId = (router.routesById[routeId] as AnyRoute).parentRoute
|
|
@@ -62,10 +66,15 @@ export const Match = React.memo(function MatchImpl({
|
|
|
62
66
|
// and reconcileMatchPool reuses stores for the same matchId.
|
|
63
67
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
64
68
|
const matchStore = router.stores.activeMatchStoresById.get(matchId)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
if (!matchStore) {
|
|
70
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
invariant()
|
|
77
|
+
}
|
|
69
78
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
70
79
|
const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt)
|
|
71
80
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -162,7 +171,9 @@ function MatchView({
|
|
|
162
171
|
onCatch={(error, errorInfo) => {
|
|
163
172
|
// Forward not found errors (we don't want to show the error component for these)
|
|
164
173
|
if (isNotFound(error)) throw error
|
|
165
|
-
|
|
174
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
175
|
+
console.warn(`Warning: Error in route match: ${matchId}`)
|
|
176
|
+
}
|
|
166
177
|
routeOnCatch?.(error, errorInfo)
|
|
167
178
|
}}
|
|
168
179
|
>
|
|
@@ -249,10 +260,15 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
249
260
|
|
|
250
261
|
if (isServer ?? router.isServer) {
|
|
251
262
|
const match = router.stores.activeMatchStoresById.get(matchId)?.state
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
263
|
+
if (!match) {
|
|
264
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
265
|
+
throw new Error(
|
|
266
|
+
`Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
invariant()
|
|
271
|
+
}
|
|
256
272
|
|
|
257
273
|
const routeId = match.routeId as string
|
|
258
274
|
const route = router.routesById[routeId] as AnyRoute
|
|
@@ -282,12 +298,24 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
282
298
|
}
|
|
283
299
|
|
|
284
300
|
if (match.status === 'notFound') {
|
|
285
|
-
|
|
301
|
+
if (!isNotFound(match.error)) {
|
|
302
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
303
|
+
throw new Error('Invariant failed: Expected a notFound error')
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
invariant()
|
|
307
|
+
}
|
|
286
308
|
return renderRouteNotFound(router, route, match.error)
|
|
287
309
|
}
|
|
288
310
|
|
|
289
311
|
if (match.status === 'redirected') {
|
|
290
|
-
|
|
312
|
+
if (!isRedirect(match.error)) {
|
|
313
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
314
|
+
throw new Error('Invariant failed: Expected a redirect error')
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
invariant()
|
|
318
|
+
}
|
|
291
319
|
throw router.getMatch(match.id)?._nonReactive.loadPromise
|
|
292
320
|
}
|
|
293
321
|
|
|
@@ -312,10 +340,15 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
312
340
|
|
|
313
341
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
314
342
|
const matchStore = router.stores.activeMatchStoresById.get(matchId)
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
343
|
+
if (!matchStore) {
|
|
344
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
345
|
+
throw new Error(
|
|
346
|
+
`Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
|
|
347
|
+
)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
invariant()
|
|
351
|
+
}
|
|
319
352
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
320
353
|
const match = useStore(matchStore, (value) => value)
|
|
321
354
|
const routeId = match.routeId as string
|
|
@@ -384,14 +417,26 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
384
417
|
}
|
|
385
418
|
|
|
386
419
|
if (match.status === 'notFound') {
|
|
387
|
-
|
|
420
|
+
if (!isNotFound(match.error)) {
|
|
421
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
422
|
+
throw new Error('Invariant failed: Expected a notFound error')
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
invariant()
|
|
426
|
+
}
|
|
388
427
|
return renderRouteNotFound(router, route, match.error)
|
|
389
428
|
}
|
|
390
429
|
|
|
391
430
|
if (match.status === 'redirected') {
|
|
392
431
|
// Redirects should be handled by the router transition. If we happen to
|
|
393
432
|
// encounter a redirect here, it's a bug. Let's warn, but render nothing.
|
|
394
|
-
|
|
433
|
+
if (!isRedirect(match.error)) {
|
|
434
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
435
|
+
throw new Error('Invariant failed: Expected a redirect error')
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
invariant()
|
|
439
|
+
}
|
|
395
440
|
|
|
396
441
|
// warning(
|
|
397
442
|
// false,
|
|
@@ -479,7 +524,15 @@ export const Outlet = React.memo(function OutletImpl() {
|
|
|
479
524
|
) : null
|
|
480
525
|
|
|
481
526
|
if (parentGlobalNotFound) {
|
|
482
|
-
|
|
527
|
+
if (!route) {
|
|
528
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
529
|
+
throw new Error(
|
|
530
|
+
'Invariant failed: Could not resolve route for Outlet render',
|
|
531
|
+
)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
invariant()
|
|
535
|
+
}
|
|
483
536
|
return renderRouteNotFound(router, route, undefined)
|
|
484
537
|
}
|
|
485
538
|
|
package/src/Matches.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import warning from 'tiny-warning'
|
|
3
2
|
import { useStore } from '@tanstack/react-store'
|
|
4
3
|
import { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'
|
|
5
4
|
import { isServer } from '@tanstack/router-core/isServer'
|
|
@@ -100,11 +99,10 @@ function MatchesInner() {
|
|
|
100
99
|
onCatch={
|
|
101
100
|
process.env.NODE_ENV !== 'production'
|
|
102
101
|
? (error) => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
`The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
|
|
102
|
+
console.warn(
|
|
103
|
+
`Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
|
|
106
104
|
)
|
|
107
|
-
|
|
105
|
+
console.warn(`Warning: ${error.message || error.toString()}`)
|
|
108
106
|
}
|
|
109
107
|
: undefined
|
|
110
108
|
}
|
package/src/fileRoute.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import warning from 'tiny-warning'
|
|
2
1
|
import { createRoute } from './route'
|
|
3
2
|
|
|
4
3
|
import { useMatch } from './useMatch'
|
|
@@ -151,10 +150,11 @@ export class FileRoute<
|
|
|
151
150
|
THandlers
|
|
152
151
|
> => {
|
|
153
152
|
if (process.env.NODE_ENV !== 'production') {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
if (!this.silent) {
|
|
154
|
+
console.warn(
|
|
155
|
+
'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
158
|
}
|
|
159
159
|
const route = createRoute(options as any)
|
|
160
160
|
;(route as any).isRoot = false
|
|
@@ -187,9 +187,8 @@ export function FileRouteLoader<
|
|
|
187
187
|
>,
|
|
188
188
|
) => TLoaderFn {
|
|
189
189
|
if (process.env.NODE_ENV !== 'production') {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
`FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
|
|
190
|
+
console.warn(
|
|
191
|
+
`Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
|
|
193
192
|
)
|
|
194
193
|
}
|
|
195
194
|
return (loaderFn) => loaderFn as any
|
|
@@ -218,7 +217,6 @@ export class LazyRoute<TRoute extends AnyRoute> {
|
|
|
218
217
|
} & LazyRouteOptions,
|
|
219
218
|
) {
|
|
220
219
|
this.options = opts
|
|
221
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
222
220
|
}
|
|
223
221
|
|
|
224
222
|
useMatch: UseMatchRoute<TRoute['id']> = (opts) => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import warning from 'tiny-warning'
|
|
3
2
|
import { DefaultGlobalNotFound } from './not-found'
|
|
4
3
|
import type { AnyRoute, AnyRouter } from '@tanstack/router-core'
|
|
5
4
|
|
|
@@ -21,11 +20,12 @@ export function renderRouteNotFound(
|
|
|
21
20
|
return <router.options.defaultNotFoundComponent {...data} />
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
if (process.env.NODE_ENV
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
24
|
+
if (!route.options.notFoundComponent) {
|
|
25
|
+
console.warn(
|
|
26
|
+
`Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<p>Not Found</p>)`,
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
return <DefaultGlobalNotFound />
|
package/src/route.tsx
CHANGED
|
@@ -258,7 +258,6 @@ export class Route<
|
|
|
258
258
|
>,
|
|
259
259
|
) {
|
|
260
260
|
super(options)
|
|
261
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
262
261
|
}
|
|
263
262
|
|
|
264
263
|
useMatch: UseMatchRoute<TId> = (opts) => {
|
|
@@ -530,7 +529,6 @@ export class RootRoute<
|
|
|
530
529
|
>,
|
|
531
530
|
) {
|
|
532
531
|
super(options)
|
|
533
|
-
;(this as any).$$typeof = Symbol.for('react.memo')
|
|
534
532
|
}
|
|
535
533
|
|
|
536
534
|
useMatch: UseMatchRoute<RootRouteId> = (opts) => {
|
package/src/useMatch.tsx
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { useStore } from '@tanstack/react-store'
|
|
3
|
-
import { replaceEqualDeep } from '@tanstack/router-core'
|
|
3
|
+
import { invariant, replaceEqualDeep } from '@tanstack/router-core'
|
|
4
4
|
import { isServer } from '@tanstack/router-core/isServer'
|
|
5
|
-
import invariant from 'tiny-invariant'
|
|
6
5
|
import { dummyMatchContext, matchContext } from './matchContext'
|
|
7
6
|
import { useRouter } from './useRouter'
|
|
8
7
|
import type {
|
|
@@ -119,10 +118,15 @@ export function useMatch<
|
|
|
119
118
|
|
|
120
119
|
if (isServer ?? router.isServer) {
|
|
121
120
|
const match = matchStore?.state
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
if ((opts.shouldThrow ?? true) && !match) {
|
|
122
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
invariant()
|
|
129
|
+
}
|
|
126
130
|
|
|
127
131
|
if (match === undefined) {
|
|
128
132
|
return undefined as any
|
|
@@ -139,10 +143,15 @@ export function useMatch<
|
|
|
139
143
|
|
|
140
144
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
|
|
141
145
|
return useStore(matchStore ?? dummyStore, (match) => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
if ((opts.shouldThrow ?? true) && !match) {
|
|
147
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
invariant()
|
|
154
|
+
}
|
|
146
155
|
|
|
147
156
|
if (match === undefined) {
|
|
148
157
|
return undefined
|
package/src/useRouter.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import warning from 'tiny-warning'
|
|
3
2
|
import { routerContext } from './routerContext'
|
|
4
3
|
import type { AnyRouter, RegisteredRouter } from '@tanstack/router-core'
|
|
5
4
|
|
|
@@ -17,9 +16,12 @@ export function useRouter<TRouter extends AnyRouter = RegisteredRouter>(opts?: {
|
|
|
17
16
|
warn?: boolean
|
|
18
17
|
}): TRouter {
|
|
19
18
|
const value = React.useContext(routerContext)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
20
|
+
if ((opts?.warn ?? true) && !value) {
|
|
21
|
+
console.warn(
|
|
22
|
+
'Warning: useRouter must be used inside a <RouterProvider> component!',
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
24
26
|
return value as any
|
|
25
27
|
}
|