-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: add Route.redirect and getRouteApi.redirect #6373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughThis pull request introduces a new route-bound redirect API surface. The Route and RouteApi types now expose a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
|
View your CI Pipeline Execution ↗ for commit c913f75
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @docs/router/framework/react/api/router/RouteApiType.md:
- Around line 152-182: The docs show RouteApi.redirect as redirect(opts?:
RedirectOptions): Redirect but the text says "all options except from" and
implies from is injected; update the signature to reflect that by changing it to
redirect(opts: Omit<RedirectOptions, 'from'>): Redirect (i.e., make the opts
parameter required and omit 'from' from RedirectOptions) and adjust the
surrounding description to match this signature; reference the RouteApi.redirect
method, RedirectOptions type, and Redirect return type when making the change.
In @packages/router-core/src/route.ts:
- Around line 778-786: Update the doc comment for Route.redirect:
RedirectFnRoute<TFullPath> to consistently use "full path" terminology instead
of "route’s path" (e.g., change "this route's path" to "this route's full path"
or "this route's fullPath") and ensure the description and examples (if any)
reference TFullPath meaningfully so the docs align with the type parameter.
🧹 Nitpick comments (4)
packages/router-core/src/redirect.ts (1)
58-86: Consider aligning default generic params withRedirectOptions(notablyTMaskTo) for consistency.
Right nowRedirectOptionsRoutedefaultsTMaskToto''whileRedirectOptionsdefaults it to'.', which can make inference/expectations differ betweenredirect()andRoute.redirect().packages/router-core/src/route.ts (1)
1917-1925: Preventopts.fromfrom overriding the auto-boundfrom.
Using{ from: this.fullPath, ...opts }allows anany-cast caller to overridefrom, which contradicts the API contract.Proposed fix
- redirect: RedirectFnRoute<TFullPath> = (opts) => - redirect({ from: this.fullPath, ...opts } as any) + redirect: RedirectFnRoute<TFullPath> = (opts) => + redirect({ ...opts, from: this.fullPath } as any)packages/router-core/tests/redirect.test-d.ts (1)
1-140: Add a runtime assertion thatfromis actually auto-populated in.options(not just “returns Response”).
Right now the tests would still pass iffromstopped being injected.Proposed test tightening
test('should create redirect with to option', () => { @@ const result = usersRoute.redirect({ to: '/' }) expectTypeOf(result).toMatchTypeOf<Response>() + expectTypeOf((result as any).options.from).toEqualTypeOf<'/users/$userId'>() }) }) @@ test('should create redirect with to option', () => { const routeApi = new BaseRouteApi({ id: '/users/$userId' }) @@ const result = routeApi.redirect({ to: '/' }) expectTypeOf(result).toMatchTypeOf<Response>() + expectTypeOf((result as any).options.from).toEqualTypeOf<string>() }) })docs/router/framework/react/api/router/redirectFunction.md (1)
85-103: Minor style nit: "outside of" → "outside".Per static analysis, "outside of" is redundant.
📝 Suggested change
### Using getRouteApi().redirect -For accessing the redirect method outside of the route definition file, you can use `getRouteApi`: +For accessing the redirect method outside the route definition file, you can use `getRouteApi`:
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
docs/router/framework/react/api/router/RouteApiType.mddocs/router/framework/react/api/router/RouteType.mddocs/router/framework/react/api/router/redirectFunction.mde2e/react-router/basic-file-based/src/routeTree.gen.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsxe2e/react-router/basic-file-based/tests/redirect.spec.tspackages/router-core/src/index.tspackages/router-core/src/redirect.tspackages/router-core/src/route.tspackages/router-core/tests/redirect.test-d.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsxpackages/router-core/src/index.tse2e/react-router/basic-file-based/tests/redirect.spec.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsxpackages/router-core/src/redirect.tspackages/router-core/tests/redirect.test-d.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxpackages/router-core/src/route.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsxpackages/router-core/src/index.tse2e/react-router/basic-file-based/tests/redirect.spec.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsxpackages/router-core/src/redirect.tspackages/router-core/tests/redirect.test-d.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxpackages/router-core/src/route.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use relative links to
docs/folder format (e.g.,./guide/data-loading) for internal documentation references
Files:
docs/router/framework/react/api/router/RouteType.mddocs/router/framework/react/api/router/redirectFunction.mddocs/router/framework/react/api/router/RouteApiType.md
🧠 Learnings (10)
📓 Common learnings
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.
Applied to files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsxpackages/router-core/src/index.tse2e/react-router/basic-file-based/tests/redirect.spec.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsxdocs/router/framework/react/api/router/RouteType.mdpackages/router-core/src/redirect.tsdocs/router/framework/react/api/router/redirectFunction.mddocs/router/framework/react/api/router/RouteApiType.mdpackages/router-core/tests/redirect.test-d.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxpackages/router-core/src/route.tse2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Applied to files:
packages/router-core/src/index.tse2e/react-router/basic-file-based/tests/redirect.spec.tspackages/router-core/tests/redirect.test-d.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
packages/router-core/src/index.tspackages/router-core/tests/redirect.test-d.tse2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
docs/router/framework/react/api/router/redirectFunction.md
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxe2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsxe2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.
Applied to files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.
Applied to files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxpackages/router-core/src/route.tse2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.
Applied to files:
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsxpackages/router-core/src/route.tse2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.
Applied to files:
e2e/react-router/basic-file-based/src/routeTree.gen.ts
🧬 Code graph analysis (7)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (5)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
Route(3-9)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
Route(3-17)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
Route(3-20)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
Route(7-21)packages/router-core/src/route.ts (1)
Route(588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (4)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
Route(3-9)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
Route(3-20)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
Route(7-21)packages/router-core/src/route.ts (1)
Route(588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (5)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
Route(3-9)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
Route(3-17)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
Route(7-21)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
Route(5-22)packages/router-core/src/index.ts (1)
Route(159-159)
packages/router-core/tests/redirect.test-d.ts (3)
packages/router-core/src/index.ts (5)
RedirectFnRoute(366-366)RedirectOptionsRoute(365-365)BaseRoute(109-109)BaseRouteApi(109-109)redirect(372-372)packages/router-core/src/redirect.ts (3)
RedirectFnRoute(77-85)RedirectOptionsRoute(62-70)redirect(104-147)packages/router-core/src/route.ts (2)
BaseRoute(1545-1926)BaseRouteApi(1928-1949)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (2)
packages/router-core/src/index.ts (1)
Route(159-159)packages/router-core/src/route.ts (1)
Route(588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx (6)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
Route(3-9)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
Route(3-17)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
Route(3-20)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
Route(7-21)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
Route(5-22)packages/router-core/src/index.ts (1)
Route(159-159)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (4)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
Route(3-9)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
Route(3-20)e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
Route(5-22)packages/router-core/src/route.ts (1)
Route(588-786)
🪛 LanguageTool
docs/router/framework/react/api/router/redirectFunction.md
[style] ~87-~87: This phrase is redundant. Consider using “outside”.
Context: ...rect For accessing the redirect method outside of the route definition file, you can use ...
(OUTSIDE_OF)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (14)
packages/router-core/src/index.ts (1)
362-369: Public exports look good (new redirect route-bound types are discoverable).packages/router-core/src/route.ts (1)
4-9: No circular dependency issue with theredirectimport.The import of
redirectfrom./redirectdoes not create a circular dependency. Whileroute.ts→redirect.ts→router.tsforms a chain,redirect.tsdoes not import fromroute.ts(only type imports fromrouter.ts), so the cycle is broken. Additionally, theredirect()function calls at lines 1925 and 1948 occur in class method definitions that are lazily bound at call time, not during module initialization, so bundling and init order remain stable.e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
1-22: LGTM! Test route correctly exercisesgetRouteApi().redirect()in loader context.The implementation is consistent with sibling route variants (via-route-redirect-loader, via-routeApi-redirect-beforeLoad). The relative redirect to
../destinationproperly tests the key feature of automaticfromparameter binding.e2e/react-router/basic-file-based/tests/redirect.spec.ts (2)
137-205: Comprehensive test coverage forRoute.redirect()API.Good use of test matrices to cover
beforeLoadandloaderthrowers across internal relative redirects and external redirects. The tests properly validate:
- URL navigation to
/redirect/internal/destination- Visibility of
redirect-destinationtest element- External redirect URL resolution
207-275: Parallel test coverage forgetRouteApi().redirect()confirms API parity.The symmetric test structure between
Route.redirect()andgetRouteApi().redirect()test blocks ensures both APIs behave consistently for internal relative and external redirects.e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
1-17: LGTM! Clean demonstration ofRoute.redirect()inbeforeLoadcontext.The implementation correctly showcases the key feature: type-safe relative redirects without needing to specify
from. ThebeforeLoadhook has direct access tosearchparams, makingloaderDepsunnecessary here (unlike the loader variant).docs/router/framework/react/api/router/redirectFunction.md (2)
57-83: Excellent documentation forRoute.redirect()with practical examples.The examples clearly demonstrate both
beforeLoadandloaderusage with relative paths (../login,./migrate), which is the key feature of this API. The inline comments explaining the redirect destinations are helpful.
105-111: Clear summary of route-bound redirect benefits.The three-point benefits list effectively communicates the value proposition over the standalone
redirectfunction.e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
1-20: LGTM! DemonstratesRoute.redirect()in loader context withloaderDeps.The implementation correctly uses
loaderDepsto passexternalHostto the loader (since loaders don't have directsearchaccess likebeforeLoad). This pairs well with thevia-route-redirect-beforeLoad.tsxvariant to demonstrate both hook contexts.docs/router/framework/react/api/router/RouteType.md (1)
29-51: LGTM! Well-documented new API surface.The documentation clearly explains the
.redirectmethod's type-safe behavior, auto-binding offromto the route'sfullPath, and includes a practical example demonstrating relative redirects in abeforeLoadguard. The internal documentation links correctly use relative paths as per coding guidelines.e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
1-9: LGTM! Clean test destination route.Simple and focused route module serving as the redirect target for the new
Route.redirectandrouteApi.redirecte2e tests. Thedata-testidattribute enables reliable test assertions.e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx (1)
63-116: LGTM! Consistent test navigation links.The new
Linkelements follow the established pattern in this file and provide comprehensive coverage for bothRoute.redirect()andgetRouteApi().redirect()scenarios acrossbeforeLoadandloaderhooks. The comments clearly delineate test groups.e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
1-21: LGTM! Well-structured test route forrouteApi.redirect().The implementation correctly demonstrates the
getRouteApi().redirect()API with both internal (relative../destination) and external redirect scenarios. The pattern is consistent with the siblingvia-route-redirect-*routes that useRoute.redirect()directly.e2e/react-router/basic-file-based/src/routeTree.gen.ts (1)
1-9: Skipping review of autogenerated file.This file is autogenerated by TanStack Router and should not be manually modified. Based on learnings,
routeTree.gen.tsfiles are excluded from review.
|
|
||
| ### `redirect` method | ||
|
|
||
| ```tsx | ||
| redirect(opts?: RedirectOptions): Redirect | ||
| ``` | ||
|
|
||
| - A type-safe version of the [`redirect`](./redirectFunction.md) function that is pre-bound to the route ID that the `RouteApi` instance was created with. | ||
| - The `from` parameter is automatically set to the route ID, enabling type-safe relative redirects. | ||
| - Options | ||
| - All options from [`redirect`](./redirectFunction.md) except `from`, which is automatically provided. | ||
| - Returns | ||
| - A `Redirect` object that can be thrown from `beforeLoad` or `loader` callbacks. | ||
|
|
||
| #### Example | ||
|
|
||
| ```tsx | ||
| import { getRouteApi } from '@tanstack/react-router' | ||
|
|
||
| const routeApi = getRouteApi('/dashboard/settings') | ||
|
|
||
| export const Route = createFileRoute('/dashboard/settings')({ | ||
| beforeLoad: ({ context }) => { | ||
| if (!context.user) { | ||
| // Type-safe redirect - 'from' is automatically '/dashboard/settings' | ||
| throw routeApi.redirect({ | ||
| to: '../login', // Relative path to sibling route | ||
| }) | ||
| } | ||
| }, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc signature should reflect “options without from” (and likely shouldn’t be optional).
The section says RedirectOptions, but the described behavior is “all redirect options except from”. Consider updating the signature text accordingly to avoid confusion.
Proposed doc edit
```tsx
- redirect(opts?: RedirectOptions): Redirect
+ redirect(opts: Omit<RedirectOptions, 'from'>): Redirect@@
-- Options
-
- All options from
redirectexceptfrom, which is automatically provided.
+- Options
- All options from
-
- All options from
redirectexceptfrom, which is automatically provided.
- All options from
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In @docs/router/framework/react/api/router/RouteApiType.md around lines 152 -
182, The docs show RouteApi.redirect as redirect(opts?: RedirectOptions):
Redirect but the text says "all options except from" and implies from is
injected; update the signature to reflect that by changing it to redirect(opts:
Omit<RedirectOptions, 'from'>): Redirect (i.e., make the opts parameter required
and omit 'from' from RedirectOptions) and adjust the surrounding description to
match this signature; reference the RouteApi.redirect method, RedirectOptions
type, and Redirect return type when making the change.
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
| /** | ||
| * Create a redirect with `from` automatically set to this route's path. | ||
| * Enables relative redirects like `Route.redirect({ to: './overview' })`. | ||
| * @param opts Redirect options (same as `redirect()` but without `from`) | ||
| * @returns A redirect Response that can be thrown from loaders/beforeLoad | ||
| * @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction | ||
| */ | ||
| redirect: RedirectFnRoute<TFullPath> | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Route.redirect: RedirectFnRoute<TFullPath> matches the goal and reads well.
Small doc nit: the text says “route’s path”, but this is TFullPath (full path), so consider using “fullPath” terminology here too.
🤖 Prompt for AI Agents
In @packages/router-core/src/route.ts around lines 778 - 786, Update the doc
comment for Route.redirect: RedirectFnRoute<TFullPath> to consistently use "full
path" terminology instead of "route’s path" (e.g., change "this route's path" to
"this route's full path" or "this route's fullPath") and ensure the description
and examples (if any) reference TFullPath meaningfully so the docs align with
the type parameter.
| /** | ||
| * Create a redirect with `from` automatically set to this route's path. | ||
| * Enables relative redirects like `routeApi.redirect({ to: './overview' })`. | ||
| * @param opts Redirect options (same as `redirect()` but without `from`) | ||
| * @returns A redirect Response that can be thrown from loaders/beforeLoad | ||
| * @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction | ||
| */ | ||
| redirect: RedirectFnRoute<RouteTypesById<TRouter, TId>['fullPath']> = ( | ||
| opts, | ||
| ) => redirect({ from: this.id as string, ...opts } as any) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's find the NavigateOptions definition and understand what 'from' represents
echo "=== Searching for NavigateOptions type ==="
rg -n "export type NavigateOptions|interface NavigateOptions" packages/router-core/src -A 15 | head -100
echo -e "\n=== Searching for 'from' property in NavigateOptions ==="
rg -n "from\s*\??:\s*" packages/router-core/src -B 2 -A 2 | grep -A 5 -B 5 "NavigateOptions\|RouteId\|fullPath" | head -100Repository: TanStack/router
Length of output: 4203
🏁 Script executed:
#!/bin/bash
# Check redirect resolution and how 'from' is processed
echo "=== Searching for redirect resolution logic ==="
rg -n "resolveRedirect|buildLocation" packages/router-core/src --type=ts -B 2 -A 5 | head -150
echo -e "\n=== Searching for how 'from' is used in routing ==="
rg -n "options\.from|\.from\s*\)" packages/router-core/src --type=ts -B 2 -A 2 | head -100Repository: TanStack/router
Length of output: 10658
🏁 Script executed:
#!/bin/bash
# Look at the actual redirect type and how it processes 'from'
echo "=== Finding redirect function definition ==="
rg -n "export.*redirect\s*=" packages/router-core/src --type=ts -A 10 | head -150
echo -e "\n=== Searching for relative path resolution with 'from' ==="
rg -n "resolveFromPath|resolvePath|ResolveRelativePath" packages/router-core/src --type=ts -B 2 -A 5 | head -100Repository: TanStack/router
Length of output: 6403
🏁 Script executed:
#!/bin/bash
# Check how RouteTypesById works and what 'fullPath' represents
echo "=== Understanding RouteTypesById and fullPath ==="
rg -n "RouteTypesById|type.*fullPath" packages/router-core/src --type=ts -B 1 -A 3 | head -150Repository: TanStack/router
Length of output: 2232
🏁 Script executed:
#!/bin/bash
# Check if opts can contain 'from' and whether spread order matters
echo "=== Checking RedirectOptions type definition ==="
rg -n "interface RedirectOptions|type RedirectOptions" packages/router-core/src --type=ts -A 15 | head -100
echo -e "\n=== Check RouteApi redirect method context ==="
sed -n '1910,1950p' packages/router-core/src/route.ts
echo -e "\n=== Verify if from is ever passed in opts to redirect ==="
rg -n "redirect\s*\(\s*\{[^}]*from" packages/router-core/src --type=ts | head -20Repository: TanStack/router
Length of output: 4286
🏁 Script executed:
#!/bin/bash
# Check the redirect function signature to understand what happens with duplicate 'from'
echo "=== Finding redirect function definition ==="
rg -n "^export.*function redirect|^export const redirect" packages/router-core/src --type=ts -A 20 | head -150Repository: TanStack/router
Length of output: 1762
🏁 Script executed:
#!/bin/bash
# Verify what 'from' actually represents in buildLocation and path resolution
echo "=== Check how from is used in buildLocation ==="
sed -n '1631,1680p' packages/router-core/src/router.ts
echo -e "\n=== Check getMatchedRoutes to understand if from is route id ==="
rg -n "getMatchedRoutes" packages/router-core/src/router.ts -A 8 | head -80Repository: TanStack/router
Length of output: 3467
🏁 Script executed:
#!/bin/bash
# Clarify what the type parameter in RedirectFnRoute means
echo "=== Check RedirectFnRoute interface ==="
sed -n '72,100p' packages/router-core/src/redirect.tsRepository: TanStack/router
Length of output: 1475
🏁 Script executed:
#!/bin/bash
# Determine if route ids can be used as paths or if fullPath is needed
echo "=== Check if Route and BaseRouteApi have different implementations ==="
rg -n "class Route\b|class BaseRouteApi" packages/router-core/src/route.ts -A 50 | grep -A 40 "redirect:"
echo -e "\n=== Search for usage examples of BaseRouteApi.redirect or RouteApi.redirect ==="
rg -n "routeApi\.redirect|\.redirect\(" packages/router-core/src --type=ts | grep -i "routeapi\|baseRouteApi" | head -20Repository: TanStack/router
Length of output: 1411
🏁 Script executed:
#!/bin/bash
# Check if route id and fullPath are ever used interchangeably
echo "=== Verify RouteApi vs Route context ==="
sed -n '1900,1950p' packages/router-core/src/route.ts
echo -e "\n=== Check if id and fullPath are same in some cases ==="
rg -n "this\.id.*===.*this\.fullPath|this\.fullPath.*===.*this\.id" packages/router-core/src --type=tsRepository: TanStack/router
Length of output: 1789
🏁 Script executed:
#!/bin/bash
# Final verification: is Route.redirect using fullPath the correct pattern?
echo "=== Check Route implementation context ==="
sed -n '1600,1630p' packages/router-core/src/route.ts
echo -e "\n=== Confirm Route.redirect uses fullPath ==="
sed -n '1918,1926p' packages/router-core/src/route.ts
echo -e "\n=== Understand RouteTypesById to verify type semantics ==="
rg -n "type RouteTypesById" packages/router-core/src/route.ts -A 5Repository: TanStack/router
Length of output: 1481
Fix JSDoc and update from parameter in BaseRouteApi.redirect from route id to fullPath.
The JSDoc says from is set to "this route's path", but the implementation uses this.id (a route id), creating a semantic mismatch with the type parameter RouteTypesById<TRouter, TId>['fullPath']. In buildLocation (router.ts:1644), from is compared to fullPath and used as a pathname, not as a route id. This means the implementation should either use the route's fullPath or clarify that from accepts route ids. For consistency with Route.redirect (line 1925, which uses from: this.fullPath) and how from is actually consumed, BaseRouteApi.redirect should pass the fullPath.
Adjust the spread order defensively: { ...opts, from: this.id } prevents accidental override (though RedirectOptionsRoute omits 'from' anyway).
| function checkAuth() { | ||
| if (!user) { | ||
| // Type-safe redirect with automatic 'from' parameter | ||
| throw routeApi.redirect({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this produce a confusing navigation history? Via getRouteApi, you can produce a redirect where from points to a different route where you've actually issued the redirect. This example is fine, but the API itself has this footgun.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this API just allows you to use relative notation for building redirect targets. has nothing to do with navigation history
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, misread the intention then. Excited for this one to land!
Summary by CodeRabbit
Release Notes
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.