Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tanstack/router/llms.txt
Use this file to discover all available pages before exploring further.
React Router
TanStack Router provides first-class support for React with type-safe components, hooks, and patterns designed specifically for React applications.
Installation
npm install @tanstack/react-router
Core Components
RouterProvider
The top-level component that renders active route matches and provides the router to the React tree via context.
import { RouterProvider, createRouter } from '@tanstack/react-router'
const router = createRouter({ routeTree })
function App() {
return <RouterProvider router={router} />
}
Link
Type-safe navigation component with preloading and active state support.
import { Link } from '@tanstack/react-router'
function Navigation() {
return (
<Link
to="/posts/$postId"
params={{ postId: '123' }}
activeProps={{
className: 'font-bold',
}}
activeOptions={{ exact: true }}
>
View Post
</Link>
)
}
Key Props:
to - Type-safe destination path
params - Path parameters
search - Search parameters
activeProps - Props applied when link is active
inactiveProps - Props applied when link is inactive
preload - Controls preloading behavior (false, 'intent', 'viewport')
disabled - Disables navigation
Outlet
Renders child route matches at the current level.
import { Outlet } from '@tanstack/react-router'
function LayoutComponent() {
return (
<div>
<header>Header</header>
<main>
<Outlet />
</main>
</div>
)
}
ErrorComponent
Default error boundary component that displays error details.
import { ErrorComponent } from '@tanstack/react-router'
import type { ErrorComponentProps } from '@tanstack/react-router'
function CustomErrorComponent({ error }: ErrorComponentProps) {
if (error instanceof NotFoundError) {
return <div>{error.message}</div>
}
return <ErrorComponent error={error} />
}
Navigate
Component-based navigation trigger.
import { Navigate } from '@tanstack/react-router'
function RedirectComponent() {
return <Navigate to="/home" />
}
React Hooks
useRouter
Access the router instance from any component.
import { useRouter } from '@tanstack/react-router'
function MyComponent() {
const router = useRouter()
const handleNavigate = () => {
router.navigate({ to: '/about' })
}
return <button onClick={handleNavigate}>Go to About</button>
}
useNavigate
Type-safe programmatic navigation.
import { useNavigate } from '@tanstack/react-router'
function MyComponent() {
const navigate = useNavigate({ from: '/posts' })
const handleClick = () => {
navigate({ to: '/posts/$postId', params: { postId: '123' } })
}
return <button onClick={handleClick}>View Post</button>
}
useParams
Access route path parameters with type safety.
import { useParams } from '@tanstack/react-router'
function PostComponent() {
const params = useParams({ from: '/posts/$postId' })
return <div>Post ID: {params.postId}</div>
}
useSearch
Access route search parameters with type safety.
import { useSearch } from '@tanstack/react-router'
function PostsComponent() {
const search = useSearch({ from: '/posts' })
return <div>Filter: {search.filter}</div>
}
useLoaderData
Access data loaded by the route’s loader function.
import { useLoaderData } from '@tanstack/react-router'
function PostComponent() {
const post = useLoaderData({ from: '/posts/$postId' })
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
)
}
useMatch
Access the current route match with full type safety.
import { useMatch } from '@tanstack/react-router'
function MyComponent() {
const match = useMatch({ from: '/posts/$postId' })
return (
<div>
<p>Status: {match.status}</p>
<p>Post ID: {match.params.postId}</p>
</div>
)
}
useRouteContext
Access route context provided by parent routes.
import { useRouteContext } from '@tanstack/react-router'
function MyComponent() {
const context = useRouteContext({ from: '/posts/$postId' })
return <div>User: {context.user.name}</div>
}
useLocation
Access the current location object.
import { useLocation } from '@tanstack/react-router'
function MyComponent() {
const location = useLocation()
return (
<div>
<p>Pathname: {location.pathname}</p>
<p>Hash: {location.hash}</p>
</div>
)
}
useRouterState
Access router state with optional selector.
import { useRouterState } from '@tanstack/react-router'
function MyComponent() {
const isLoading = useRouterState({
select: (state) => state.isLoading,
})
return isLoading ? <div>Loading...</div> : null
}
useMatchRoute
Check if a specific route matches the current location.
import { useMatchRoute } from '@tanstack/react-router'
function MyComponent() {
const matchRoute = useMatchRoute()
const isPostsRoute = matchRoute({ to: '/posts' })
return <div>{isPostsRoute ? 'On Posts Page' : 'Not on Posts Page'}</div>
}
useLinkProps
Build anchor-like props for custom link components.
import { useLinkProps } from '@tanstack/react-router'
function CustomLink(props) {
const linkProps = useLinkProps(props)
return <a {...linkProps} className="custom-link" />
}
useBlocker
Block navigation based on a condition (useful for unsaved changes).
import { useBlocker } from '@tanstack/react-router'
function FormComponent() {
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
useBlocker({
condition: hasUnsavedChanges,
blockerFn: () => window.confirm('You have unsaved changes. Leave anyway?'),
})
return <form>...</form>
}
Route API
RouteApi
Route-specific API with pre-bound hooks for a specific route ID.
import { getRouteApi } from '@tanstack/react-router'
const postRoute = getRouteApi('/posts/$postId')
function PostComponent() {
const params = postRoute.useParams()
const post = postRoute.useLoaderData()
const navigate = postRoute.useNavigate()
return (
<div>
<h1>{post.title}</h1>
<postRoute.Link to="/posts">Back to Posts</postRoute.Link>
</div>
)
}
Creating Routes
Code-based Routes
import { createRoute, createRootRoute } from '@tanstack/react-router'
const rootRoute = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<>
<nav>...</nav>
<Outlet />
</>
)
}
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: IndexComponent,
})
function IndexComponent() {
return <div>Welcome Home!</div>
}
const postRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/posts/$postId',
loader: ({ params }) => fetchPost(params.postId),
component: PostComponent,
})
function PostComponent() {
const post = postRoute.useLoaderData()
return <div>{post.title}</div>
}
const routeTree = rootRoute.addChildren([indexRoute, postRoute])
File-based Routes
// src/routes/__root.tsx
import { createRootRoute, Outlet } from '@tanstack/react-router'
export const Route = createRootRoute({
component: () => (
<>
<nav>...</nav>
<Outlet />
</>
),
})
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: () => <div>Welcome Home!</div>,
})
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params }) => fetchPost(params.postId),
component: PostComponent,
})
function PostComponent() {
const post = Route.useLoaderData()
return <div>{post.title}</div>
}
SSR Support
React Router includes specialized SSR utilities:
// Server-side
import { createMemoryHistory } from '@tanstack/react-router'
const history = createMemoryHistory({
initialEntries: [request.url],
})
const router = createRouter({
routeTree,
history,
})
await router.load()
const html = ReactDOMServer.renderToString(
<RouterProvider router={router} />
)
// Client-side
import { createBrowserHistory } from '@tanstack/react-router'
const history = createBrowserHistory()
const router = createRouter({ routeTree, history })
ReactDOM.hydrateRoot(
document.getElementById('root'),
<RouterProvider router={router} />
)
React-Specific Features
Error Boundaries
React Router integrates with React’s error boundaries:
const route = createRoute({
path: '/posts/$postId',
errorComponent: ({ error, reset }) => (
<div>
<p>Error: {error.message}</p>
<button onClick={reset}>Try Again</button>
</div>
),
})
Suspense Integration
Works seamlessly with React Suspense:
const route = createRoute({
path: '/posts',
pendingComponent: () => <div>Loading posts...</div>,
component: PostsComponent,
})
React 19 Support
Fully compatible with React 19 features including:
- Server Components (RSC)
- Server Actions
- Enhanced hydration
- View Transitions
Complete Example
import ReactDOM from 'react-dom/client'
import {
RouterProvider,
createRouter,
createRootRoute,
createRoute,
Link,
Outlet,
} from '@tanstack/react-router'
const rootRoute = createRootRoute({
component: () => (
<div>
<nav>
<Link to="/" activeProps={{ className: 'font-bold' }}>
Home
</Link>
<Link to="/posts" activeProps={{ className: 'font-bold' }}>
Posts
</Link>
</nav>
<Outlet />
</div>
),
})
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: () => <h1>Welcome Home!</h1>,
})
const postsRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/posts',
loader: () => fetch('/api/posts').then(r => r.json()),
component: PostsComponent,
})
function PostsComponent() {
const posts = postsRoute.useLoaderData()
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<Link to="/posts/$postId" params={{ postId: post.id }}>
{post.title}
</Link>
</li>
))}
</ul>
)
}
const routeTree = rootRoute.addChildren([indexRoute, postsRoute])
const router = createRouter({ routeTree })
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
const rootElement = document.getElementById('root')!
ReactDOM.createRoot(rootElement).render(<RouterProvider router={router} />)
Best Practices
-
Type Safety: Always register your router type for full type safety:
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
-
Use RouteApi: For code-split routes, use
getRouteApi instead of importing routes:
const route = getRouteApi('/posts/$postId')
const data = route.useLoaderData()
-
Preloading: Configure preloading for better UX:
const router = createRouter({
routeTree,
defaultPreload: 'intent', // preload on hover/focus
})
-
Error Handling: Provide custom error components for better UX:
const route = createRoute({
errorComponent: CustomErrorComponent,
})
-
Pending States: Use pending components for loading states:
const route = createRoute({
pendingComponent: () => <Spinner />,
})