TanStack Router: A Modern and scalable routing library for React
πΈ
PexelsOkay, 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 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
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-devtools
Create the following files:
src/routes/__root.tsx
(with two_
characters)src/routes/index.tsx
src/routes/about.tsx
src/main.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
// ROUTE
export const Route = createRootRoute({
component: RootComponent,
})
// COMPONENT
function RootComponent() {
return (
<>
<div className="p-2 flex gap-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.
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.
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/about')({
component: About,
})
function About() {
return <div className="p-2">Hello from About!</div>
}
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider, createRouter } 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>,
)
}
When you run 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
.
Folder Structure
src/
βββ routes/
β βββ __root.tsx
β βββ index.tsx
β βββ about.tsx
βββ routeTree.gen.ts
βββ main.tsx
Okay, now you know how to create the file-based routing.
Code Based Routing
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.tsx
Okay, now letβs write the code for each file.
import {createRootRoute, Outlet, Link} from "@tanstack/react-router";
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const rootRoute = createRootRoute({
component: RootComponent,
});
function RootComponent() {
return (
<>
<div className="p-2 flex gap-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold">
About
</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
);
}
import {createRoute} from "@tanstack/react-router";
import {rootRoute} from "./__root";
// ROUTE
export const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/",
component: Index,
});
// COMPONENT
function Index() {
return (
<div className="p-2 bg-green-500">
<h3>Welcome Home!</h3>
</div>
);
}
import {createRoute} from "@tanstack/react-router";
import {rootRoute} from "./__root";
// ROUTE
export const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/about",
component: About,
});
// COMPONENT
function About() {
return <div className="p-2">Hello from About!</div>;
}
import {StrictMode} from "react";
import ReactDOM from "react-dom/client";
import {
RouterProvider,
createRouter,
} from "@tanstack/react-router";
// ROUTES
import {rootRoute} from "./routes/__root";
import {indexRoute} from "./routes/index";
import {aboutRoute} from "./routes/about";
// ROUTE TREE
const routeTree = rootRoute.addChildren([
indexRoute,
aboutRoute,
]);
// Set up a Router instance
const router = createRouter({
routeTree,
scrollRestoration: true,
});
// 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>
);
}
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.
Comments
Leave a comment or reaction below!