@tanstack/react-router 1.87.12 → 1.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.87.12",
3
+ "version": "1.88.0",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -38,7 +38,7 @@ export type NavigateFn = <
38
38
  TMaskTo extends string = '',
39
39
  >(
40
40
  opts: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
41
- ) => Promise<void>
41
+ ) => Promise<void> | void
42
42
 
43
43
  export type BuildLocationFn = <
44
44
  TRouter extends RegisteredRouter,
package/src/link.tsx CHANGED
@@ -219,6 +219,8 @@ export interface NavigateOptionProps {
219
219
  // if set to `ViewTransitionOptions`, the router will pass the `types` field to document.startViewTransition({update: fn, types: viewTransition.types}) call
220
220
  viewTransition?: boolean | ViewTransitionOptions
221
221
  ignoreBlocker?: boolean
222
+ reloadDocument?: boolean
223
+ href?: string
222
224
  }
223
225
 
224
226
  export type ToOptions<
@@ -643,6 +645,9 @@ export function useLinkProps<
643
645
  // null for LinkUtils
644
646
 
645
647
  const type: 'internal' | 'external' = React.useMemo(() => {
648
+ if (rest.reloadDocument) {
649
+ return 'external'
650
+ }
646
651
  try {
647
652
  new URL(`${to}`)
648
653
  return 'external'
package/src/redirects.ts CHANGED
@@ -12,10 +12,10 @@ export type Redirect<
12
12
  TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,
13
13
  TMaskTo extends string = '.',
14
14
  > = {
15
+ href?: string
15
16
  /**
16
17
  * @deprecated Use `statusCode` instead
17
18
  **/
18
- href?: string
19
19
  code?: number
20
20
  statusCode?: number
21
21
  throw?: any
@@ -47,6 +47,14 @@ export function redirect<
47
47
  ;(opts as any).isRedirect = true
48
48
  opts.statusCode = opts.statusCode || opts.code || 307
49
49
  opts.headers = opts.headers || {}
50
+ if (!opts.reloadDocument) {
51
+ opts.reloadDocument = false
52
+ try {
53
+ new URL(`${opts.href}`)
54
+ opts.reloadDocument = true
55
+ } catch {}
56
+ }
57
+
50
58
  if (opts.throw) {
51
59
  throw opts
52
60
  }
package/src/route.ts CHANGED
@@ -569,7 +569,7 @@ export interface LoaderFnContext<
569
569
  /**
570
570
  * @deprecated Use `throw redirect({ to: '/somewhere' })` instead
571
571
  **/
572
- navigate: (opts: NavigateOptions<AnyRouter>) => Promise<void>
572
+ navigate: (opts: NavigateOptions<AnyRouter>) => Promise<void> | void
573
573
  // root route does not have a parent match
574
574
  parentMatchPromise: TId extends RootRouteId
575
575
  ? never
package/src/router.ts CHANGED
@@ -536,6 +536,7 @@ export interface BuildNextOptions {
536
536
  }
537
537
  from?: string
538
538
  _fromLocation?: ParsedLocation
539
+ href?: string
539
540
  }
540
541
 
541
542
  export interface MatchedRoutesResult {
@@ -1861,9 +1862,9 @@ export class Router<
1861
1862
  resetScroll,
1862
1863
  viewTransition,
1863
1864
  ignoreBlocker,
1865
+ href,
1864
1866
  ...rest
1865
1867
  }: BuildNextOptions & CommitLocationOptions = {}) => {
1866
- const href = (rest as any).href
1867
1868
  if (href) {
1868
1869
  const parsed = parseHref(href, {})
1869
1870
  rest.to = parsed.pathname
@@ -1885,29 +1886,24 @@ export class Router<
1885
1886
  })
1886
1887
  }
1887
1888
 
1888
- navigate: NavigateFn = ({ to, ...rest }) => {
1889
- // If this link simply reloads the current route,
1890
- // make sure it has a new key so it will trigger a data refresh
1891
-
1892
- // If this `to` is a valid external URL, return
1893
- // null for LinkUtils
1894
- const toString = String(to)
1895
- let isExternal
1896
-
1897
- try {
1898
- new URL(`${toString}`)
1899
- isExternal = true
1900
- } catch (e) {}
1901
-
1902
- invariant(
1903
- !isExternal,
1904
- 'Attempting to navigate to external url with router.navigate!',
1905
- )
1889
+ navigate: NavigateFn = ({ to, reloadDocument, href, ...rest }) => {
1890
+ if (reloadDocument) {
1891
+ if (!href) {
1892
+ const location = this.buildLocation({ to, ...rest } as any)
1893
+ href = location.href
1894
+ }
1895
+ if (rest.replace) {
1896
+ window.location.replace(href)
1897
+ } else {
1898
+ window.location.href = href
1899
+ }
1900
+ return
1901
+ }
1906
1902
 
1907
1903
  return this.buildAndCommitLocation({
1908
1904
  ...rest,
1905
+ href,
1909
1906
  to: to as string,
1910
- // to: toString,
1911
1907
  })
1912
1908
  }
1913
1909
 
@@ -2041,7 +2037,7 @@ export class Router<
2041
2037
  redirect = err
2042
2038
  if (!this.isServer) {
2043
2039
  this.navigate({
2044
- ...err,
2040
+ ...redirect,
2045
2041
  replace: true,
2046
2042
  ignoreBlocker: true,
2047
2043
  })
@@ -2194,7 +2190,11 @@ export class Router<
2194
2190
  }
2195
2191
 
2196
2192
  const handleRedirectAndNotFound = (match: AnyRouteMatch, err: any) => {
2197
- if (isResolvedRedirect(err)) throw err
2193
+ if (isResolvedRedirect(err)) {
2194
+ if (!err.reloadDocument) {
2195
+ throw err
2196
+ }
2197
+ }
2198
2198
 
2199
2199
  if (isRedirect(err) || isNotFound(err)) {
2200
2200
  updateMatch(match.id, (prev) => ({
@@ -2877,6 +2877,9 @@ export class Router<
2877
2877
  return matches
2878
2878
  } catch (err) {
2879
2879
  if (isRedirect(err)) {
2880
+ if (err.reloadDocument) {
2881
+ return undefined
2882
+ }
2880
2883
  return await this.preloadRoute({
2881
2884
  ...(err as any),
2882
2885
  _fromLocation: next,