
TanStack Router: A Modern and scalable routing library for React
Okay, here i'm once again with another topic that i'm sure you will find useful.
Recently, i've been working on a project that uses TanStack Router and i've learned a lot about it. So, i've decided to write a guide about it.
In this guide, i'll show you how to do file-based and code-based routing and see how powerful tanstack router is.
What is TanStack Router?
TanStack Router is a fully type-safe routing solution for React applications and it will make you to fall in love with routing again ๐. Created by Tanner Linsley (the same mind behind React Query), it aims to solve many of the pain points developers face with traditional routing libraries.
So now you must be wondering what kind of features it has to offer.
- 100% inferred TypeScript support
- Typesafe navigation
- File-based routing
- Code based routing
- Code splitting
- Path and Search Parameter Schema Validation
- Built-in Route Loaders w/ SWR Caching
- Search Param Navigation APIs
- Custom Search Param parser/serializer support
- Search param middleware
- Route matching/loading middleware
Sounds cool, right?
I know you are excited knowing more about it.
Getting Started
Okay, let's code.
So TanStack Router provides two ways to create routes:
- File-based routing
- Code based routing
โน๏ธ Note
File-based routing is the recommended way to create routes.
Code based routing is the alternative way to create routes.
They are both great and i'll show you how to use both of them.
File-based Routing
So, let's start with the file-based routing.
First, install the dependencies:
npm install @tanstack/react-router @tanstack/react-router-devtoolsCreate the following files:
src/routes/__root.tsx(with two_characters)src/routes/index.tsxsrc/routes/about.tsxsrc/main.tsx
// src/routes/__root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const Route = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<>
<div className="flex gap-2 p-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold">
About
</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
)
}Root route is the parent of all routes. It contains the common layout and components for all routes. Think of it as the Layout component of Next.js.
// src/routes/index.tsx
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/')({
component: Index,
})
function Index() {
return (
<div className="p-2">
<h3>Welcome Home!</h3>
</div>
)
}Here i'm using the createLazyFileRoute function to create the file based route. but you can also use the createFileRoute function. the difference between them is that createLazyFileRoute is used for lazy loading the route and createFileRoute is used for normal routes.
// src/routes/about.tsx
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/about')({
component: About,
})
function About() {
return <div className="p-2">Hello from About!</div>
}// src/main.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
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
}
}
// Render the app
const rootElement = document.getElementById('root')!
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)
}๐ก Tip
When you run
npm run dev/npm run buildscripts, or manually run thetsr watch/tsr generatecommands from your package scripts, the route tree file will be generated atsrc/routeTree.gen.ts.
Folder Structure
src/
โโโ routes/
โ โโโ __root.tsx
โ โโโ index.tsx
โ โโโ about.tsx
โโโ routeTree.gen.ts
โโโ main.tsxOkay, now you know how to create the file-based routing.
Code Based Routing
โน๏ธ Note
Since they recommend splitting routes into separate files for better organization and performance as our application grows, i'll show you how to do that.
It is gonna be a bit confusing, so i'll first show you the folder structure and then i'll write the code for each file.
Folder Structure
src/
โโโ routes/
โ โโโ __root.tsx
โ โโโ index.tsx
โ โโโ about.tsx
โโโ routeTree.gen.ts
โโโ main.tsxOkay, now let's write the code for each file.
// src/routes/__root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const rootRoute = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<>
<div className="flex gap-2 p-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold">
About
</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
)
}// src/routes/index.tsx
import { createRoute } from '@tanstack/react-router'
import { rootRoute } from './__root'
export const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: Index,
})
function Index() {
return (
<div className="bg-green-500 p-2">
<h3>Welcome Home!</h3>
</div>
)
}// src/routes/about.tsx
import { createRoute } from '@tanstack/react-router'
import { rootRoute } from './__root'
export const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
component: About,
})
function About() {
return <div className="p-2">Hello from About!</div>
}// src/main.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import { createRouter, RouterProvider } from '@tanstack/react-router'
import { rootRoute } from './routes/__root'
import { aboutRoute } from './routes/about'
import { indexRoute } from './routes/index'
const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
const router = createRouter({
routeTree,
scrollRestoration: true,
})
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
const rootElement = document.getElementById('root')!
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)
}Booyah ๐, we did it man.
Now you know how to do file-based and code-based routing and what are the differences between them and why you should try it.
Conclusion
Okay, see i'm totally in love with file-based routing it has made my life so much easier in terms of organization routing and managing Search Param APIs.
Tanner Linsley โค๏ธ is a genius, i'm not kidding. he has made routing easier and simpler than ever.
Give it a try and you will love it too ๐.
Cheers ๐ฅ. Comment down below if you have any questions or feedback.