Before you begin your journey in migrating from React Location, it's important that you have a good understanding of the Routing Concepts and Design Decisions used by TanStack Router.
React Location and TanStack Router share much of same design decisions concepts, but there are some key differences that you should be aware of.
In this guide we'll go over the process of migrating the React Location Basic example over to TanStack Router using file-based routing, with the end goal of having the same functionality as the original example (styling and other non-routing related code will be omitted).
To use a code-based approach for defining your routes, you can read the code-based Routing guide.
First, we need to install the dependencies for TanStack Router. For detailed installation instructions, see our How to Install TanStack Router guide.
npm install @tanstack/react-router @tanstack/router-devtools npm install @tanstack/react-router @tanstack/router-devtools And remove the React Location dependencies.
npm uninstall @tanstack/react-location @tanstack/react-location-devtools npm uninstall @tanstack/react-location @tanstack/react-location-devtools If your project uses Vite (or one of the supported bundlers), you can use the TanStack Router plugin to watch for changes in your routes files and automatically update the routes configuration.
Installation of the Vite plugin:
npm install -D @tanstack/router-plugin npm install -D @tanstack/router-plugin And add it to your vite.config.js:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { tanstackRouter } from '@tanstack/router-plugin/vite' export default defineConfig({ // ... plugins: [tanstackRouter(), react()], }) import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { tanstackRouter } from '@tanstack/router-plugin/vite' export default defineConfig({ // ... plugins: [tanstackRouter(), react()], }) However, if your application does not use Vite, you use one of our other supported bundlers, or you can use the @tanstack/router-cli package to watch for changes in your routes files and automatically update the routes configuration.
Create a tsr.config.json file in the root of your project with the following content:
{ "routesDirectory": "./src/routes", "generatedRouteTree": "./src/routeTree.gen.ts" } { "routesDirectory": "./src/routes", "generatedRouteTree": "./src/routeTree.gen.ts" } You can find the full list of options for the tsr.config.json file here.
Create a routes directory in the src directory of your project.
mkdir src/routes mkdir src/routes // src/routes/__root.tsx import { createRootRoute, Outlet, Link } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/router-devtools' export const Route = createRootRoute({ component: () => { return ( <> <div> <Link to="/" activeOptions={{ exact: true }}> Home </Link> <Link to="/posts">Posts</Link> </div> <hr /> <Outlet /> <TanStackRouterDevtools /> </> ) }, }) // src/routes/__root.tsx import { createRootRoute, Outlet, Link } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/router-devtools' export const Route = createRootRoute({ component: () => { return ( <> <div> <Link to="/" activeOptions={{ exact: true }}> Home </Link> <Link to="/posts">Posts</Link> </div> <hr /> <Outlet /> <TanStackRouterDevtools /> </> ) }, }) // src/routes/index.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/')({ component: Index, }) // src/routes/index.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/')({ component: Index, }) You will need to move any related components and logic needed for the index route from the src/index.tsx file to the src/routes/index.tsx file.
// src/routes/posts.tsx import { createFileRoute, Link, Outlet } from '@tanstack/react-router' export const Route = createFileRoute('/posts')({ component: Posts, loader: async () => { const posts = await fetchPosts() return { posts, } }, }) function Posts() { const { posts } = Route.useLoaderData() return ( <div> <nav> {posts.map((post) => ( <Link key={post.id} to={`/posts/$postId`} params={{ postId: post.id }} > {post.title} </Link> ))} </nav> <Outlet /> </div> ) } // src/routes/posts.tsx import { createFileRoute, Link, Outlet } from '@tanstack/react-router' export const Route = createFileRoute('/posts')({ component: Posts, loader: async () => { const posts = await fetchPosts() return { posts, } }, }) function Posts() { const { posts } = Route.useLoaderData() return ( <div> <nav> {posts.map((post) => ( <Link key={post.id} to={`/posts/$postId`} params={{ postId: post.id }} > {post.title} </Link> ))} </nav> <Outlet /> </div> ) } You will need to move any related components and logic needed for the posts route from the src/index.tsx file to the src/routes/posts.tsx file.
// src/routes/posts.index.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/posts/')({ component: PostsIndex, }) // src/routes/posts.index.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/posts/')({ component: PostsIndex, }) You will need to move any related components and logic needed for the posts index route from the src/index.tsx file to the src/routes/posts.index.tsx file.
// src/routes/posts.$postId.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/posts/$postId')({ component: PostsId, loader: async ({ params: { postId } }) => { const post = await fetchPost(postId) return { post, } }, }) function PostsId() { const { post } = Route.useLoaderData() // ... } // src/routes/posts.$postId.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/posts/$postId')({ component: PostsId, loader: async ({ params: { postId } }) => { const post = await fetchPost(postId) return { post, } }, }) function PostsId() { const { post } = Route.useLoaderData() // ... } You will need to move any related components and logic needed for the posts id route from the src/index.tsx file to the src/routes/posts.$postId.tsx file.
If you are using one of the supported bundlers, the route tree will be generated automatically when you run the dev script.
If you are not using one of the supported bundlers, you can generate the route tree by running the following command:
npx tsr generate npx tsr generate Once you've generated the route-tree, you can then update the src/index.tsx file to create the router instance and render it.
// src/index.tsx import React from 'react' import ReactDOM from 'react-dom' import { createRouter, RouterProvider } from '@tanstack/react-router' // Import the generated route tree import { routeTree } from './routeTree.gen' // Create a new router instance const router = createRouter({ routeTree }) // Register the router instance for type safety declare module '@tanstack/react-router' { interface Register { router: typeof router } } const domElementId = 'root' // Assuming you have a root element with the id 'root' // Render the app const rootElement = document.getElementById(domElementId) if (!rootElement) { throw new Error(`Element with id ${domElementId} not found`) } ReactDOM.createRoot(rootElement).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode>, ) // src/index.tsx import React from 'react' import ReactDOM from 'react-dom' import { createRouter, RouterProvider } from '@tanstack/react-router' // Import the generated route tree import { routeTree } from './routeTree.gen' // Create a new router instance const router = createRouter({ routeTree }) // Register the router instance for type safety declare module '@tanstack/react-router' { interface Register { router: typeof router } } const domElementId = 'root' // Assuming you have a root element with the id 'root' // Render the app const rootElement = document.getElementById(domElementId) if (!rootElement) { throw new Error(`Element with id ${domElementId} not found`) } ReactDOM.createRoot(rootElement).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode>, ) You should now have successfully migrated your application from React Location to TanStack Router using file-based routing.
React Location also has a few more features that you might be using in your application. Here are some guides to help you migrate those features:
TanStack Router also has a few more features that you might want to explore:
If you are facing any issues or have any questions, feel free to ask for help in the TanStack Discord.
