@tanstack/react-router 1.132.47 → 1.133.3

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.
@@ -161,247 +161,139 @@ Enough overview, there's so much more to do with TanStack Router. Hit that next
161
161
 
162
162
  # Quick Start
163
163
 
164
- If you're feeling impatient and prefer to skip all of our wonderful documentation, here is the bare minimum to get going with TanStack Router using both file-based route generation and code-based route configuration:
164
+ TanStack Router can be quickly added to any existing React project or used to scaffold a new one.
165
165
 
166
- ## Using File-Based Route Generation
166
+ ## TanStack Router Installation
167
167
 
168
- File based route generation (through Vite, and other supported bundlers) is the recommended way to use TanStack Router as it provides the best experience, performance, and ergonomics for the least amount of effort.
168
+ ### Requirements
169
169
 
170
- ### Scaffolding Your First TanStack Router Project
170
+ Before installing TanStack router, please ensure your project meets the following requirements:
171
171
 
172
- \`\`\`sh
173
- npx create-tsrouter-app@latest my-app --template file-router
174
- \`\`\`
172
+ [//]: # 'Requirements'
173
+
174
+ - \`react\` v18 or later with \`createRoot\` support.
175
+ - \`react-dom\` v18 or later.
175
176
 
176
- See [create-tsrouter-app](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app) for more options.
177
+ [//]: # 'Requirements'
177
178
 
178
- ### Manual Setup
179
+ > [!NOTE] Using TypeScript (\`v5.3.x or higher\`) is recommended for the best development experience, though not strictly required. We aim to support the last 5 minor versions of TypeScript, but using the latest version will help avoid potential issues.
179
180
 
180
- Alternatively, you can manually setup the project using the following steps:
181
+ TanStack Router is currently only compatible with React (with ReactDOM) and Solid. If you're interested in contributing to support other frameworks, such as React Native, Angular, or Vue, please reach out to us on [Discord](https://tlinz.com/discord).
181
182
 
182
- #### Install TanStack Router, Vite Plugin, and the Router Devtools
183
+ ### Download and Install
184
+
185
+ To install TanStack Router in your project, run the following command using your preferred package manager:
186
+
187
+ [//]: # 'installCommand'
183
188
 
184
189
  \`\`\`sh
185
- npm install @tanstack/react-router @tanstack/react-router-devtools
186
- npm install -D @tanstack/router-plugin
187
- # or
188
- pnpm add @tanstack/react-router @tanstack/react-router-devtools
189
- pnpm add -D @tanstack/router-plugin
190
+ npm install @tanstack/router
190
191
  # or
191
- yarn add @tanstack/react-router @tanstack/react-router-devtools
192
- yarn add -D @tanstack/router-plugin
192
+ pnpm add @tanstack/router
193
+ #or
194
+ yarn add @tanstack/router
193
195
  # or
194
- bun add @tanstack/react-router @tanstack/react-router-devtools
195
- bun add -D @tanstack/router-plugin
196
+ bun add @tanstack/router
196
197
  # or
197
- deno add npm:@tanstack/react-router npm:@tanstack/router-plugin npm:@tanstack/react-router-devtools
198
+ deno add npm:@tanstack/router
198
199
  \`\`\`
199
200
 
200
- #### Configure the Vite Plugin
201
+ [//]: # 'installCommand'
201
202
 
202
- \`\`\`tsx
203
- // vite.config.ts
204
- import { defineConfig } from 'vite'
205
- import react from '@vitejs/plugin-react'
206
- import { tanstackRouter } from '@tanstack/router-plugin/vite'
203
+ Once installed, you can verify the installation by checking your \`package.json\` file for the \`@tanstack/router\` dependency.
207
204
 
208
- // https://vitejs.dev/config/
209
- export default defineConfig({
210
- plugins: [
211
- // Please make sure that '@tanstack/router-plugin' is passed before '@vitejs/plugin-react'
212
- tanstackRouter({
213
- target: 'react',
214
- autoCodeSplitting: true,
215
- }),
216
- react(),
217
- // ...,
218
- ],
219
- })
205
+ [//]: # 'packageJson'
206
+
207
+ \`\`\`json
208
+ {
209
+ "dependencies": {
210
+ "@tanstack/react-router": "^x.x.x"
211
+ }
212
+ }
220
213
  \`\`\`
221
214
 
222
- > [!TIP]
223
- > If you are not using Vite, or any of the supported bundlers, you can check out the [TanStack Router CLI](../routing/installation-with-router-cli.md) guide for more info.
215
+ [//]: # 'packageJson'
224
216
 
225
- Create the following files:
217
+ ## New Project Setup
226
218
 
227
- - \`src/routes/__root.tsx\` (with two '\`_\`' characters)
228
- - \`src/routes/index.tsx\`
229
- - \`src/routes/about.tsx\`
230
- - \`src/main.tsx\`
219
+ To quickly scaffold a new project with TanStack Router, you can use the \`create-tsrouter-app\` command-line tool. This tool sets up a new React application with TanStack Router pre-configured, allowing you to get started quickly.
231
220
 
232
- #### \`src/routes/__root.tsx\`
221
+ > [!TIP] For full details on available options and templates, visit the [\`create-tsrouter-app\` documentation](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app).
233
222
 
234
- \`\`\`tsx
235
- import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
236
- import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
223
+ To create a new project, run the following command in your terminal:
237
224
 
238
- const RootLayout = () => (
239
- <>
240
- <div className="p-2 flex gap-2">
241
- <Link to="/" className="[&.active]:font-bold">
242
- Home
243
- </Link>{' '}
244
- <Link to="/about" className="[&.active]:font-bold">
245
- About
246
- </Link>
247
- </div>
248
- <hr />
249
- <Outlet />
250
- <TanStackRouterDevtools />
251
- </>
252
- )
225
+ [//]: # 'createAppCommand'
253
226
 
254
- export const Route = createRootRoute({ component: RootLayout })
227
+ \`\`\`sh
228
+ npx create-tsrouter-app@latest
255
229
  \`\`\`
256
230
 
257
- #### \`src/routes/index.tsx\`
258
-
259
- \`\`\`tsx
260
- import { createFileRoute } from '@tanstack/react-router'
231
+ [//]: # 'createAppCommand'
261
232
 
262
- export const Route = createFileRoute('/')({
263
- component: Index,
264
- })
233
+ The CLI will guide you through a short series of prompts to customize your setup, including options for:
265
234
 
266
- function Index() {
267
- return (
268
- <div className="p-2">
269
- <h3>Welcome Home!</h3>
270
- </div>
271
- )
272
- }
273
- \`\`\`
235
+ [//]: # 'CLIPrompts'
274
236
 
275
- #### \`src/routes/about.tsx\`
237
+ - File-based or code-based route configuration
238
+ - TypeScript support
239
+ - Tailwind CSS integration
240
+ - Toolchain setup
241
+ - Git initialization
276
242
 
277
- \`\`\`tsx
278
- import { createFileRoute } from '@tanstack/react-router'
243
+ [//]: # 'CLIPrompts'
279
244
 
280
- export const Route = createFileRoute('/about')({
281
- component: About,
282
- })
245
+ Once complete, a new React project will be generated with TanStack Router installed and ready to use. All dependencies are automatically installed, so you can jump straight into development:
283
246
 
284
- function About() {
285
- return <div className="p-2">Hello from About!</div>
286
- }
247
+ \`\`\`sh
248
+ cd your-project-name
249
+ npm run dev
287
250
  \`\`\`
288
251
 
289
- #### \`src/main.tsx\`
252
+ ### Routing Options
290
253
 
291
- Regardless of whether you are using the \`@tanstack/router-plugin\` package and running the \`npm run dev\`/\`npm run build\` scripts, or manually running the \`tsr watch\`/\`tsr generate\` commands from your package scripts, the route tree file will be generated at \`src/routeTree.gen.ts\`.
254
+ TanStack Router supports both file-based and code-based route configurations, allowing you to choose the approach that best fits your workflow.
292
255
 
293
- Import the generated route tree and create a new router instance:
256
+ #### File-Based Route Generation
294
257
 
295
- \`\`\`tsx
296
- import { StrictMode } from 'react'
297
- import ReactDOM from 'react-dom/client'
298
- import { RouterProvider, createRouter } from '@tanstack/react-router'
258
+ The file-based approach is the recommended option for most projects. It automatically creates routes based on your file structure, giving you the best mix of performance, simplicity, and developer experience.
299
259
 
300
- // Import the generated route tree
301
- import { routeTree } from './routeTree.gen'
260
+ To create a new project using file-based route generation, run the following command:
302
261
 
303
- // Create a new router instance
304
- const router = createRouter({ routeTree })
305
-
306
- // Register the router instance for type safety
307
- declare module '@tanstack/react-router' {
308
- interface Register {
309
- router: typeof router
310
- }
311
- }
262
+ [//]: # 'createAppCommandFileBased'
312
263
 
313
- // Render the app
314
- const rootElement = document.getElementById('root')!
315
- if (!rootElement.innerHTML) {
316
- const root = ReactDOM.createRoot(rootElement)
317
- root.render(
318
- <StrictMode>
319
- <RouterProvider router={router} />
320
- </StrictMode>,
321
- )
322
- }
264
+ \`\`\`sh
265
+ npx create-tsrouter-app@latest my-app --template file-router
323
266
  \`\`\`
324
267
 
325
- If you are working with this pattern you should change the \`id\` of the root \`<div>\` on your \`index.html\` file to \`<div id='root'></div>\`
268
+ [//]: # 'createAppCommandFileBased'
326
269
 
327
- ## Using Code-Based Route Configuration
270
+ This command sets up a new directory called \`my-app\` with everything configured. Once setup completes, you can then start your development server and begin building your application:
328
271
 
329
- > [!IMPORTANT]
330
- > The following example shows how to configure routes using code, and for simplicity's sake is in a single file for this demo. While code-based generation allows you to declare many routes and even the router instance in a single file, we recommend splitting your routes into separate files for better organization and performance as your application grows.
272
+ \`\`\`sh
273
+ cd my-app
274
+ npm run dev
275
+ \`\`\`
331
276
 
332
- \`\`\`tsx
333
- import { StrictMode } from 'react'
334
- import ReactDOM from 'react-dom/client'
335
- import {
336
- Outlet,
337
- RouterProvider,
338
- Link,
339
- createRouter,
340
- createRoute,
341
- createRootRoute,
342
- } from '@tanstack/react-router'
343
- import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
277
+ #### Code-Based Route Configuration
344
278
 
345
- const rootRoute = createRootRoute({
346
- component: () => (
347
- <>
348
- <div className="p-2 flex gap-2">
349
- <Link to="/" className="[&.active]:font-bold">
350
- Home
351
- </Link>{' '}
352
- <Link to="/about" className="[&.active]:font-bold">
353
- About
354
- </Link>
355
- </div>
356
- <hr />
357
- <Outlet />
358
- <TanStackRouterDevtools />
359
- </>
360
- ),
361
- })
279
+ If you prefer to define routes programmatically, you can use the code-based route configuration. This approach gives you full control over routing logic while maintaining the same project scaffolding workflow.
362
280
 
363
- const indexRoute = createRoute({
364
- getParentRoute: () => rootRoute,
365
- path: '/',
366
- component: function Index() {
367
- return (
368
- <div className="p-2">
369
- <h3>Welcome Home!</h3>
370
- </div>
371
- )
372
- },
373
- })
281
+ [//]: # 'createAppCommandCodeBased'
374
282
 
375
- const aboutRoute = createRoute({
376
- getParentRoute: () => rootRoute,
377
- path: '/about',
378
- component: function About() {
379
- return <div className="p-2">Hello from About!</div>
380
- },
381
- })
283
+ \`\`\`sh
284
+ npx create-tsrouter-app@latest my-app
285
+ \`\`\`
382
286
 
383
- const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
287
+ [//]: # 'createAppCommandCodeBased'
384
288
 
385
- const router = createRouter({ routeTree })
289
+ Similar to the file-based setup, this command creates a new directory called \`my-app\` with TanStack Router configured for code-based routing. After setup, navigate to your project directory and start the development server:
386
290
 
387
- declare module '@tanstack/react-router' {
388
- interface Register {
389
- router: typeof router
390
- }
391
- }
392
-
393
- const rootElement = document.getElementById('app')!
394
- if (!rootElement.innerHTML) {
395
- const root = ReactDOM.createRoot(rootElement)
396
- root.render(
397
- <StrictMode>
398
- <RouterProvider router={router} />
399
- </StrictMode>,
400
- )
401
- }
291
+ \`\`\`sh
292
+ cd my-app
293
+ npm run dev
402
294
  \`\`\`
403
295
 
404
- If you glossed over these examples or didn't understand something, we don't blame you, because there's so much more to learn to really take advantage of TanStack Router! Let's move on.
296
+ With either approach, you can now start building your React application with TanStack Router!
405
297
 
406
298
  # Devtools
407
299
 
@@ -593,37 +485,748 @@ function App() {
593
485
  - Specifies a Shadow DOM target for the devtools.
594
486
  - By default, devtool styles are applied to the \`<head>\` tag of the main document (light DOM). When a \`shadowDOMTarget\` is provided, styles will be applied within this Shadow DOM instead.
595
487
 
596
- # Migration from React Router Checklist
597
-
598
- **_If your UI is blank, open the console, and you will probably have some errors that read something along the lines of \`cannot use 'useNavigate' outside of context\` . This means there are React Router api’s that are still imported and referenced that you need to find and remove. The easiest way to make sure you find all React Router imports is to uninstall \`react-router-dom\` and then you should get typescript errors in your files. Then you will know what to change to a \`@tanstack/react-router\` import._**
599
-
600
- Here is the [example repo](https://github.com/Benanna2019/SickFitsForEveryone/tree/migrate-to-tanstack/router/React-Router)
601
-
602
- - [ ] Install Router - \`npm i @tanstack/react-router\` (see [detailed installation guide](../how-to/install.md))
603
- - [ ] **Optional:** Uninstall React Router to get TypeScript errors on imports.
604
- - At this point I don’t know if you can do a gradual migration, but it seems likely you could have multiple router providers, not desirable.
605
- - The api’s between React Router and TanStack Router are very similar and could most likely be handled in a sprint cycle or two if that is your companies way of doing things.
606
- - [ ] Create Routes for each existing React Router route we have
607
- - [ ] Create root route
608
- - [ ] Create router instance
609
- - [ ] Add global module in main.tsx
610
- - [ ] Remove any React Router (\`createBrowserRouter\` or \`BrowserRouter\`), \`Routes\`, and \`Route\` Components from main.tsx
611
- - [ ] **Optional:** Refactor \`render\` function for custom setup/providers - The repo referenced above has an example - This was necessary in the case of Supertokens. Supertoken has a specific setup with React Router and a different setup with all other React implementations
612
- - [ ] Set RouterProvider and pass it the router as the prop
613
- - [ ] Replace all instances of React Router \`Link\` component with \`@tanstack/react-router\` \`Link\` component
614
- - [ ] Add \`to\` prop with literal path
615
- - [ ] Add \`params\` prop, where necessary with params like so \`params={{ orderId: order.id }}\`
616
- - [ ] Replace all instances of React Router \`useNavigate\` hook with \`@tanstack/react-router\` \`useNavigate\` hook
617
- - [ ] Set \`to\` property and \`params\` property where needed
618
- - [ ] Replace any React Router \`Outlet\`'s with the \`@tanstack/react-router\` equivalent
619
- - [ ] If you are using \`useSearchParams\` hook from React Router, move the search params default value to the validateSearch property on a Route definition.
620
- - [ ] Instead of using the \`useSearchParams\` hook, use \`@tanstack/react-router\` \`Link\`'s search property to update the search params state
621
- - [ ] To read search params you can do something like the following
622
- - \`const { page } = useSearch({ from: productPage.fullPath })\`
623
- - [ ] If using React Router’s \`useParams\` hook, update the import to be from \`@tanstack/react-router\` and set the \`from\` property to the literal path name where you want to read the params object from
624
- - So say we have a route with the path name \`orders/$orderid\`.
625
- - In the \`useParams\` hook we would set up our hook like so: \`const params = useParams({ from: "/orders/$orderId" })\`
626
- - Then wherever we wanted to access the order id we would get it off of the params object \`params.orderId\`
488
+ # How to Migrate from React Router v7
489
+
490
+ This guide provides a step-by-step process to migrate your application from React Router v7 to TanStack Router. We'll cover the complete migration process from removing React Router dependencies to implementing TanStack Router's type-safe routing patterns.
491
+
492
+ ## Quick Start
493
+
494
+ **Time Required:** 2-4 hours depending on app complexity
495
+ **Difficulty:** Intermediate
496
+ **Prerequisites:** Basic React knowledge, existing React Router v7 app
497
+
498
+ ### What You'll Accomplish
499
+
500
+ - Remove React Router v7 dependencies and components
501
+ - Install and configure TanStack Router
502
+ - Convert route definitions to file-based routing
503
+ - Update navigation components and hooks
504
+ - Implement type-safe routing patterns
505
+ - Handle search params and dynamic routes
506
+ - Migrate from React Router v7's new features to TanStack Router equivalents
507
+
508
+ ---
509
+
510
+ ## Complete Migration Process
511
+
512
+ ### Step 1: Prepare for Migration
513
+
514
+ Before making any changes, prepare your environment and codebase:
515
+
516
+ **1.1 Create a backup branch**
517
+
518
+ \`\`\`bash
519
+ git checkout -b migrate-to-tanstack-router
520
+ git push -u origin migrate-to-tanstack-router
521
+ \`\`\`
522
+
523
+ **1.2 Install TanStack Router (keep React Router temporarily)**
524
+
525
+ \`\`\`bash
526
+ # Install TanStack Router
527
+ npm install @tanstack/react-router
528
+
529
+ # Install development dependencies
530
+ npm install -D @tanstack/router-plugin @tanstack/react-router-devtools
531
+ \`\`\`
532
+
533
+ **1.3 Set up the router plugin for your bundler**
534
+
535
+ For **Vite** users, update your \`vite.config.ts\`:
536
+
537
+ \`\`\`typescript
538
+ import { defineConfig } from 'vite'
539
+ import react from '@vitejs/plugin-react'
540
+ import { tanstackRouter } from '@tanstack/router-plugin/vite'
541
+
542
+ export default defineConfig({
543
+ plugins: [
544
+ tanstackRouter(), // Add this before react plugin
545
+ react(),
546
+ ],
547
+ })
548
+ \`\`\`
549
+
550
+ For **other bundlers**, see our [bundler configuration guides](../routing/).
551
+
552
+ ### Step 2: Create TanStack Router Configuration
553
+
554
+ **2.1 Create router configuration file**
555
+
556
+ Create \`tsr.config.json\` in your project root:
557
+
558
+ \`\`\`json
559
+ {
560
+ "routesDirectory": "./src/routes",
561
+ "generatedRouteTree": "./src/routeTree.gen.ts",
562
+ "quoteStyle": "single"
563
+ }
564
+ \`\`\`
565
+
566
+ **2.2 Create routes directory**
567
+
568
+ \`\`\`bash
569
+ mkdir src/routes
570
+ \`\`\`
571
+
572
+ ### Step 3: Convert Your React Router v7 Structure
573
+
574
+ **3.1 Identify your current React Router v7 setup**
575
+
576
+ React Router v7 introduced several new patterns. Look for:
577
+
578
+ - \`createBrowserRouter\` with new data APIs
579
+ - Framework mode configurations
580
+ - Server-side rendering setup
581
+ - New \`loader\` and \`action\` functions
582
+ - \`defer\` usage (simplified in v7)
583
+ - Type-safe routing features
584
+
585
+ **3.2 Create root route**
586
+
587
+ Create \`src/routes/__root.tsx\`:
588
+
589
+ \`\`\`typescript
590
+ import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
591
+ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
592
+
593
+ export const Route = createRootRoute({
594
+ component: () => (
595
+ <>
596
+ {/* Your existing layout/navbar content */}
597
+ <div className="p-2 flex gap-2">
598
+ <Link to="/" className="[&.active]:font-bold">
599
+ Home
600
+ </Link>
601
+ <Link to="/about" className="[&.active]:font-bold">
602
+ About
603
+ </Link>
604
+ </div>
605
+ <hr />
606
+ <Outlet />
607
+ <TanStackRouterDevtools />
608
+ </>
609
+ ),
610
+ })
611
+ \`\`\`
612
+
613
+ **3.3 Create index route**
614
+
615
+ Create \`src/routes/index.tsx\` for your home page:
616
+
617
+ \`\`\`typescript
618
+ import { createFileRoute } from '@tanstack/react-router'
619
+
620
+ export const Route = createFileRoute('/')({
621
+ component: Index,
622
+ })
623
+
624
+ function Index() {
625
+ return (
626
+ <div className="p-2">
627
+ <h3>Welcome Home!</h3>
628
+ </div>
629
+ )
630
+ }
631
+ \`\`\`
632
+
633
+ **3.4 Convert React Router v7 loaders**
634
+
635
+ React Router v7 simplified loader patterns. Here's how to migrate them:
636
+
637
+ **React Router v7:**
638
+
639
+ \`\`\`typescript
640
+ // app/routes/posts.tsx
641
+ export async function loader() {
642
+ const posts = await fetchPosts()
643
+ return { posts } // v7 removed need for json() wrapper
644
+ }
645
+
646
+ export default function Posts() {
647
+ const { posts } = useLoaderData()
648
+ return <div>{/* render posts */}</div>
649
+ }
650
+ \`\`\`
651
+
652
+ **TanStack Router equivalent:**
653
+ Create \`src/routes/posts.tsx\`:
654
+
655
+ \`\`\`typescript
656
+ import { createFileRoute } from '@tanstack/react-router'
657
+
658
+ export const Route = createFileRoute('/posts')({
659
+ loader: async () => {
660
+ const posts = await fetchPosts()
661
+ return { posts }
662
+ },
663
+ component: Posts,
664
+ })
665
+
666
+ function Posts() {
667
+ const { posts } = Route.useLoaderData()
668
+ return <div>{/* render posts */}</div>
669
+ }
670
+ \`\`\`
671
+
672
+ **3.5 Convert dynamic routes**
673
+
674
+ **React Router v7:**
675
+
676
+ \`\`\`typescript
677
+ // app/routes/posts.$postId.tsx
678
+ export async function loader({ params }) {
679
+ const post = await fetchPost(params.postId)
680
+ return { post }
681
+ }
682
+
683
+ export default function Post() {
684
+ const { post } = useLoaderData()
685
+ return <div>{post.title}</div>
686
+ }
687
+ \`\`\`
688
+
689
+ **TanStack Router equivalent:**
690
+ Create \`src/routes/posts/$postId.tsx\`:
691
+
692
+ \`\`\`typescript
693
+ import { createFileRoute } from '@tanstack/react-router'
694
+
695
+ export const Route = createFileRoute('/posts/$postId')({
696
+ loader: async ({ params }) => {
697
+ const post = await fetchPost(params.postId)
698
+ return { post }
699
+ },
700
+ component: Post,
701
+ })
702
+
703
+ function Post() {
704
+ const { post } = Route.useLoaderData()
705
+ const { postId } = Route.useParams()
706
+ return <div>{post.title}</div>
707
+ }
708
+ \`\`\`
709
+
710
+ **3.6 Convert React Router v7 actions**
711
+
712
+ **React Router v7:**
713
+
714
+ \`\`\`typescript
715
+ export async function action({ request, params }) {
716
+ const formData = await request.formData()
717
+ const result = await updatePost(params.postId, formData)
718
+ return { success: true }
719
+ }
720
+ \`\`\`
721
+
722
+ **TanStack Router equivalent:**
723
+
724
+ \`\`\`typescript
725
+ export const Route = createFileRoute('/posts/$postId/edit')({
726
+ component: EditPost,
727
+ // Actions are typically handled differently in TanStack Router
728
+ // Use mutations or form libraries like React Hook Form
729
+ })
730
+
731
+ function EditPost() {
732
+ const navigate = useNavigate()
733
+
734
+ const handleSubmit = async (formData) => {
735
+ const result = await updatePost(params.postId, formData)
736
+ navigate({ to: '/posts/$postId', params: { postId } })
737
+ }
738
+
739
+ return <form onSubmit={handleSubmit}>{/* form */}</form>
740
+ }
741
+ \`\`\`
742
+
743
+ ### Step 4: Handle React Router v7 Framework Features
744
+
745
+ **4.1 Server-Side Rendering Migration**
746
+
747
+ React Router v7 introduced framework mode with SSR. If you're using this:
748
+
749
+ **React Router v7 Framework Mode:**
750
+
751
+ \`\`\`typescript
752
+ // react-router.config.ts
753
+ export default {
754
+ ssr: true,
755
+ prerender: ['/'],
756
+ }
757
+ \`\`\`
758
+
759
+ **TanStack Router approach:**
760
+
761
+ TanStack Router has built-in SSR capabilities. Set up your router for SSR:
762
+
763
+ \`\`\`typescript
764
+ // src/router.tsx
765
+ import { createRouter } from '@tanstack/react-router'
766
+ import { routeTree } from './routeTree.gen'
767
+
768
+ const router = createRouter({
769
+ routeTree,
770
+ context: {
771
+ // Add any SSR context here
772
+ },
773
+ })
774
+
775
+ declare module '@tanstack/react-router' {
776
+ interface Register {
777
+ router: typeof router
778
+ }
779
+ }
780
+
781
+ export { router }
782
+ \`\`\`
783
+
784
+ For server-side rendering, use TanStack Router's built-in SSR APIs:
785
+
786
+ \`\`\`typescript
787
+ // server.tsx
788
+ import { createMemoryHistory } from '@tanstack/react-router'
789
+ import { StartServer } from '@tanstack/start/server'
790
+
791
+ export async function render(url: string) {
792
+ const router = createRouter({
793
+ routeTree,
794
+ history: createMemoryHistory({ initialEntries: [url] }),
795
+ })
796
+
797
+ await router.load()
798
+
799
+ return (
800
+ <StartServer router={router} />
801
+ )
802
+ }
803
+ \`\`\`
804
+
805
+ **4.2 Code Splitting Migration**
806
+
807
+ React Router v7 improved code splitting. TanStack Router handles this via lazy routes:
808
+
809
+ **React Router v7:**
810
+
811
+ \`\`\`typescript
812
+ const LazyComponent = lazy(() => import('./LazyComponent'))
813
+ \`\`\`
814
+
815
+ **TanStack Router:**
816
+
817
+ \`\`\`typescript
818
+ import { createLazyFileRoute } from '@tanstack/react-router'
819
+
820
+ export const Route = createLazyFileRoute('/lazy-route')({
821
+ component: LazyComponent,
822
+ })
823
+
824
+ function LazyComponent() {
825
+ return <div>Lazy loaded!</div>
826
+ }
827
+ \`\`\`
828
+
829
+ ### Step 5: Update Navigation Components
830
+
831
+ **5.1 Update Link components**
832
+
833
+ **React Router v7:**
834
+
835
+ \`\`\`typescript
836
+ import { Link } from 'react-router'
837
+
838
+ <Link to="/posts/123">View Post</Link>
839
+ <Link to="/posts" state={{ from: 'home' }}>Posts</Link>
840
+ \`\`\`
841
+
842
+ **TanStack Router:**
843
+
844
+ \`\`\`typescript
845
+ import { Link } from '@tanstack/react-router'
846
+
847
+ <Link to="/posts/$postId" params={{ postId: '123' }}>View Post</Link>
848
+ <Link to="/posts" state={{ from: 'home' }}>Posts</Link>
849
+ \`\`\`
850
+
851
+ **5.2 Update navigation hooks**
852
+
853
+ **React Router v7:**
854
+
855
+ \`\`\`typescript
856
+ import { useNavigate } from 'react-router'
857
+
858
+ function Component() {
859
+ const navigate = useNavigate()
860
+
861
+ const handleClick = () => {
862
+ navigate('/posts/123')
863
+ }
864
+ }
865
+ \`\`\`
866
+
867
+ **TanStack Router:**
868
+
869
+ \`\`\`typescript
870
+ import { useNavigate } from '@tanstack/react-router'
871
+
872
+ function Component() {
873
+ const navigate = useNavigate()
874
+
875
+ const handleClick = () => {
876
+ navigate({ to: '/posts/$postId', params: { postId: '123' } })
877
+ }
878
+ }
879
+ \`\`\`
880
+
881
+ ### Step 6: Handle React Router v7 Specific Features
882
+
883
+ **6.1 Migrate simplified \`defer\` usage**
884
+
885
+ React Router v7 simplified defer by removing the wrapper function:
886
+
887
+ **React Router v7:**
888
+
889
+ \`\`\`typescript
890
+ export async function loader() {
891
+ return {
892
+ data: fetchData(), // Promise directly returned
893
+ }
894
+ }
895
+ \`\`\`
896
+
897
+ **TanStack Router:**
898
+
899
+ TanStack Router uses a different approach for deferred data. Use loading states:
900
+
901
+ \`\`\`typescript
902
+ export const Route = createFileRoute('/deferred')({
903
+ loader: async () => {
904
+ const data = await fetchData()
905
+ return { data }
906
+ },
907
+ pendingComponent: () => <div>Loading...</div>,
908
+ component: DeferredComponent,
909
+ })
910
+ \`\`\`
911
+
912
+ **6.2 Handle React Router v7's enhanced type safety**
913
+
914
+ React Router v7 improved type inference. TanStack Router provides even better type safety:
915
+
916
+ \`\`\`typescript
917
+ // TanStack Router automatically infers types
918
+ export const Route = createFileRoute('/posts/$postId')({
919
+ loader: async ({ params }) => {
920
+ // params.postId is automatically typed as string
921
+ const post = await fetchPost(params.postId)
922
+ return { post }
923
+ },
924
+ component: Post,
925
+ })
926
+
927
+ function Post() {
928
+ // post is automatically typed based on loader return
929
+ const { post } = Route.useLoaderData()
930
+ // postId is automatically typed as string
931
+ const { postId } = Route.useParams()
932
+ }
933
+ \`\`\`
934
+
935
+ ### Step 7: Update Your Main Router Setup
936
+
937
+ **7.1 Replace React Router v7 router creation**
938
+
939
+ **Before (React Router v7):**
940
+
941
+ \`\`\`typescript
942
+ import { createBrowserRouter, RouterProvider } from 'react-router'
943
+
944
+ const router = createBrowserRouter([
945
+ // Your route definitions
946
+ ])
947
+
948
+ ReactDOM.createRoot(document.getElementById('root')!).render(
949
+ <React.StrictMode>
950
+ <RouterProvider router={router} />
951
+ </React.StrictMode>,
952
+ )
953
+ \`\`\`
954
+
955
+ **After (TanStack Router):**
956
+
957
+ \`\`\`typescript
958
+ import { RouterProvider } from '@tanstack/react-router'
959
+ import { router } from './router'
960
+
961
+ ReactDOM.createRoot(document.getElementById('root')!).render(
962
+ <React.StrictMode>
963
+ <RouterProvider router={router} />
964
+ </React.StrictMode>,
965
+ )
966
+ \`\`\`
967
+
968
+ ### Step 8: Handle Search Parameters
969
+
970
+ **8.1 React Router v7 to TanStack Router search params**
971
+
972
+ **React Router v7:**
973
+
974
+ \`\`\`typescript
975
+ import { useSearchParams } from 'react-router'
976
+
977
+ function Component() {
978
+ const [searchParams, setSearchParams] = useSearchParams()
979
+ const page = searchParams.get('page') || '1'
980
+
981
+ const updatePage = (newPage) => {
982
+ setSearchParams({ page: newPage })
983
+ }
984
+ }
985
+ \`\`\`
986
+
987
+ **TanStack Router:**
988
+
989
+ \`\`\`typescript
990
+ import { createFileRoute } from '@tanstack/react-router'
991
+ import { z } from 'zod'
992
+
993
+ const searchSchema = z.object({
994
+ page: z.number().catch(1),
995
+ filter: z.string().optional(),
996
+ })
997
+
998
+ export const Route = createFileRoute('/posts')({
999
+ validateSearch: searchSchema,
1000
+ component: Posts,
1001
+ })
1002
+
1003
+ function Posts() {
1004
+ const navigate = useNavigate({ from: '/posts' })
1005
+ const { page, filter } = Route.useSearch()
1006
+
1007
+ const updatePage = (newPage: number) => {
1008
+ navigate({ search: (prev) => ({ ...prev, page: newPage }) })
1009
+ }
1010
+ }
1011
+ \`\`\`
1012
+
1013
+ ### Step 9: Remove React Router Dependencies
1014
+
1015
+ Only after everything is working with TanStack Router:
1016
+
1017
+ **9.1 Remove React Router v7**
1018
+
1019
+ \`\`\`bash
1020
+ npm uninstall react-router
1021
+ \`\`\`
1022
+
1023
+ **9.2 Clean up unused imports**
1024
+
1025
+ Search your codebase for any remaining React Router imports:
1026
+
1027
+ \`\`\`bash
1028
+ # Find remaining React Router imports
1029
+ grep -r "react-router" src/
1030
+ \`\`\`
1031
+
1032
+ Remove any remaining imports and replace with TanStack Router equivalents.
1033
+
1034
+ ### Step 10: Add Advanced Type Safety
1035
+
1036
+ **10.1 Configure strict TypeScript**
1037
+
1038
+ Update your \`tsconfig.json\`:
1039
+
1040
+ \`\`\`json
1041
+ {
1042
+ "compilerOptions": {
1043
+ "strict": true,
1044
+ "noUncheckedIndexedAccess": true
1045
+ }
1046
+ }
1047
+ \`\`\`
1048
+
1049
+ **10.2 Add search parameter validation**
1050
+
1051
+ For routes with search parameters, add validation schemas:
1052
+
1053
+ \`\`\`typescript
1054
+ import { createFileRoute } from '@tanstack/react-router'
1055
+ import { z } from 'zod'
1056
+
1057
+ const postsSearchSchema = z.object({
1058
+ page: z.number().min(1).catch(1),
1059
+ search: z.string().optional(),
1060
+ category: z.enum(['tech', 'business', 'lifestyle']).optional(),
1061
+ })
1062
+
1063
+ export const Route = createFileRoute('/posts')({
1064
+ validateSearch: postsSearchSchema,
1065
+ component: Posts,
1066
+ })
1067
+ \`\`\`
1068
+
1069
+ ---
1070
+
1071
+ ## Production Checklist
1072
+
1073
+ Before deploying your migrated application:
1074
+
1075
+ ### Router Configuration
1076
+
1077
+ - [ ] Router instance created and properly exported
1078
+ - [ ] Route tree generated successfully
1079
+ - [ ] TypeScript declarations registered
1080
+ - [ ] All route files follow naming conventions
1081
+
1082
+ ### Route Migration
1083
+
1084
+ - [ ] All React Router v7 routes converted to file-based routing
1085
+ - [ ] Dynamic routes updated with proper parameter syntax
1086
+ - [ ] Nested routes maintain hierarchy
1087
+ - [ ] Index routes created where needed
1088
+ - [ ] Layout routes preserve component structure
1089
+
1090
+ ### Feature Migration
1091
+
1092
+ - [ ] All React Router v7 loaders converted
1093
+ - [ ] Actions migrated to appropriate patterns
1094
+ - [ ] Server-side rendering configured (if applicable)
1095
+ - [ ] Code splitting implemented
1096
+ - [ ] Type safety enhanced
1097
+
1098
+ ### Navigation Updates
1099
+
1100
+ - [ ] All Link components updated to TanStack Router
1101
+ - [ ] useNavigate hooks replaced and tested
1102
+ - [ ] Navigation parameters properly typed
1103
+ - [ ] Search parameter validation implemented
1104
+
1105
+ ### Code Cleanup
1106
+
1107
+ - [ ] React Router v7 dependencies removed
1108
+ - [ ] Unused imports cleaned up
1109
+ - [ ] No React Router references remain
1110
+ - [ ] TypeScript compilation successful
1111
+ - [ ] All tests passing
1112
+
1113
+ ### Testing
1114
+
1115
+ - [ ] All routes accessible and rendering correctly
1116
+ - [ ] Navigation between routes working
1117
+ - [ ] Back/forward browser buttons functional
1118
+ - [ ] Search parameters persisting correctly
1119
+ - [ ] Dynamic routes with parameters working
1120
+ - [ ] Nested route layouts displaying properly
1121
+ - [ ] Framework features (SSR, code splitting) working if applicable
1122
+
1123
+ ---
1124
+
1125
+ ## Common Problems
1126
+
1127
+ ### Error: "Cannot use useNavigate outside of context"
1128
+
1129
+ **Problem:** You have remaining React Router imports that conflict with TanStack Router.
1130
+
1131
+ **Solution:**
1132
+
1133
+ 1. Search for all React Router imports:
1134
+ \`\`\`bash
1135
+ grep -r "react-router" src/
1136
+ \`\`\`
1137
+ 2. Replace all imports with TanStack Router equivalents
1138
+ 3. Ensure React Router is completely uninstalled
1139
+
1140
+ ### TypeScript Errors: Route Parameters
1141
+
1142
+ **Problem:** TypeScript showing errors about route parameters not being typed correctly.
1143
+
1144
+ **Solution:**
1145
+
1146
+ 1. Ensure your router is registered in the TypeScript module declaration:
1147
+ \`\`\`typescript
1148
+ declare module '@tanstack/react-router' {
1149
+ interface Register {
1150
+ router: typeof router
1151
+ }
1152
+ }
1153
+ \`\`\`
1154
+ 2. Check that your route files export the Route correctly
1155
+ 3. Verify parameter names match between route definition and usage
1156
+
1157
+ ### React Router v7 Framework Features Not Working
1158
+
1159
+ **Problem:** Missing SSR or code splitting functionality after migration.
1160
+
1161
+ **Solution:**
1162
+
1163
+ 1. TanStack Router has built-in SSR capabilities - use TanStack Start for full-stack applications
1164
+ 2. Use TanStack Router's lazy routes for code splitting
1165
+ 3. Configure SSR using TanStack Router's native APIs
1166
+ 4. Follow the [SSR setup guide](../setup-ssr.md) for detailed instructions
1167
+
1168
+ ### Routes Not Matching
1169
+
1170
+ **Problem:** Routes not rendering or 404 errors for valid routes.
1171
+
1172
+ **Solution:**
1173
+
1174
+ 1. Check file naming follows TanStack Router conventions:
1175
+ - Dynamic routes: \`$paramName.tsx\`
1176
+ - Index routes: \`index.tsx\`
1177
+ - Nested routes: proper directory structure
1178
+ 2. Verify route tree generation is working
1179
+ 3. Check that the router plugin is properly configured
1180
+
1181
+ ### React Router v7 Simplified APIs Not Translating
1182
+
1183
+ **Problem:** v7's simplified \`defer\` or other features don't have direct equivalents.
1184
+
1185
+ **Solution:**
1186
+
1187
+ 1. Use TanStack Router's pending states for loading UX
1188
+ 2. Implement data fetching patterns that fit TanStack Router's architecture
1189
+ 3. Leverage TanStack Router's superior type safety for better DX
1190
+
1191
+ ---
1192
+
1193
+ ## React Router v7 vs TanStack Router Feature Comparison
1194
+
1195
+ | Feature | React Router v7 | TanStack Router |
1196
+ | ------------------ | ------------------- | ---------------------------- |
1197
+ | Type Safety | Good | Excellent |
1198
+ | File-based Routing | Framework mode only | Built-in |
1199
+ | Search Params | Basic | Validated with schemas |
1200
+ | Code Splitting | Good | Excellent with lazy routes |
1201
+ | SSR | Framework mode | Built-in with TanStack Start |
1202
+ | Bundle Size | Larger | Smaller |
1203
+ | Learning Curve | Moderate | Moderate |
1204
+ | Community | Large | Growing |
1205
+
1206
+ ---
1207
+
1208
+ ## Common Next Steps
1209
+
1210
+ After successfully migrating to TanStack Router, consider these enhancements:
1211
+
1212
+ ### Advanced Features to Explore
1213
+
1214
+ - **Route-based code splitting** - Improve performance with lazy loading
1215
+ - **Search parameter validation** - Type-safe URL state management
1216
+ - **Route preloading** - Enhance perceived performance
1217
+ - **Route masking** - Advanced URL management
1218
+ - **Integration with TanStack Query** - Powerful data fetching
1219
+
1220
+ ---
1221
+
1222
+ ## Related Resources
1223
+
1224
+ - [TanStack Router Documentation](https://tanstack.com/router) - Complete API reference
1225
+ - [File-Based Routing Guide](../../routing/file-based-routing.md) - Detailed routing concepts
1226
+ - [Navigation Guide](../../guide/navigation.md) - Complete navigation patterns
1227
+ - [Search Parameters Guide](../../guide/search-params.md) - Advanced search param usage
1228
+ - [Type Safety Guide](../../guide/type-safety.md) - TypeScript integration details
1229
+ - [React Router v7 Changelog](https://reactrouter.com/start/changelog) - What changed in v7
627
1230
 
628
1231
  # Migration from React Location
629
1232
 
@@ -895,6 +1498,20 @@ If you are facing any issues or have any questions, feel free to ask for help in
895
1498
 
896
1499
  Welcome to the TanStack Router FAQ! Here you'll find answers to common questions about the TanStack Router. If you have a question that isn't answered here, please feel free to ask in the [TanStack Discord](https://tlinz.com/discord).
897
1500
 
1501
+ ## Why should you choose TanStack Router over another router?
1502
+
1503
+ To answer this question, it's important to view the other options in the space. There are many alternatives to choose from, but only a couple that are widely adopted and actively maintained:
1504
+
1505
+ - **Next.js** - Widely regarded as the leading framework for starting new React projects. Its design focuses on performance, development workflows, and cutting-edge technology. The framework's APIs and abstractions, while powerful, can sometimes present as non-standard. Rapid growth and industry adoption have resulted in a feature-rich experience, sometimes leading to a steeper learning curve and increased overhead.
1506
+ - **Remix / React Router** - Based on the historically successful React Router, Remix delivers a powerful developer and user experience. Its API and architectural vision are firmly rooted in web standards such as Request/Response, with an emphasis on adaptability across various JavaScript environments. Many of its APIs and abstractions are well-designed and have influenced more than a few of TanStack Router's APIs. However, its rigid design, the integration of type safety as an add-on, and sometimes strict adherence to platform APIs can present limitations for some developers.
1507
+
1508
+ These frameworks and routers have their strengths, but they also come with trade-offs that may not align with every project's needs. TanStack Router aims to strike a balance by offering routing APIs designed to improve the developer experience without sacrificing flexibility or performance.
1509
+
1510
+ ## Is TanStack Router a framework?
1511
+
1512
+ TanStack Router itself is not a "framework" in the traditional sense, since it doesn't address a few other common full-stack concerns. However, TanStack Router has been designed to be upgradable to a full-stack framework when used in conjunction with other tools that address bundling, deployments, and server-side-specific functionality. This is why we are currently developing [TanStack Start](https://tanstack.com/start), a full-stack framework that is built on top of TanStack Router and Vite.
1513
+ For a deeper dive on the history of TanStack Router, feel free to read [TanStack Router's History](../decisions-on-dx.md#tanstack-routers-origin-story).
1514
+
898
1515
  ## Should I commit my \`routeTree.gen.ts\` file into git?
899
1516
 
900
1517
  Yes! Although the route tree file (i.e., \`routeTree.gen.ts\`) is generated by TanStack Router, it is essentially part of your application’s runtime, not a build artifact. The route tree file is a critical part of your application’s source code, and it is used by TanStack Router to build your application’s routes at runtime.