Overview
TanStack Router is a fully type-safe router for React (and Solid) applications. It provides file-based routing, first-class search parameter management, built-in data loading, code splitting, and deep TypeScript integration. It serves as the routing foundation for TanStack Start (the full-stack framework).
Package: @tanstack/react-router
CLI: @tanstack/router-cli or @tanstack/router-plugin (Vite/Rspack/Webpack)
Devtools: @tanstack/react-router-devtools
Installation
Core Concepts
Route Trees
Routes are organized in a tree structure. The root route is the top-level layout, and child routes nest underneath.
File-Based Routing
File-based routing automatically generates the route tree from your file structure. Configure with Vite plugin:
File Naming Conventions
Special Prefixes
_prefix: Pathless routes (layout groups without URL segment)$prefix: Dynamic path parameters(folder)parentheses: Route groups (organizational, no URL impact)
Route Configuration
Each route can define:
Data Loading
Route Loaders
Loader Dependencies
Control when loaders re-execute:
Deferred Data Loading
Stream non-critical data:
Context-Based Data Loading
Provide shared dependencies via router context:
Search Parameters
Validation
Reading Search Params
Updating Search Params
Search Param Options
Navigation
Link Component
Programmatic Navigation
Redirects
Navigation Blocking
Code Splitting
Automatic (File-Based Routing)
With file-based routing, create a lazy file:
Manual Code Splitting
Preloading
Type Safety
Register Router Type
Type-Safe Hooks
All hooks are fully typed based on the route tree:
Route Generics
Authenticated Routes
Scroll Restoration
Route Masking
Display a different URL than the actual route:
Not Found Handling
Head Management
Integration with TanStack Query
Router Hooks Reference
Best Practices
- Use file-based routing for most applications - it's simpler and auto-generates the route tree
- Validate search params with Zod or custom validators for type safety
- Use
loaderDepsto control when loaders re-execute based on search param changes - Leverage context for dependency injection (QueryClient, auth state)
- Use
beforeLoadfor authentication guards, not in components - Separate critical vs lazy code - keep loaders in the main file, components in
.lazy.tsx - Use
preload="intent"on Links for perceived performance - Use
staleTimeto prevent unnecessary refetches during navigation - Register the router type for full TypeScript inference across the app
- Use
notFound()instead of conditional rendering for 404 states - Colocate search param logic with routes that own them
- Use pathless layouts (
_authenticated) for shared auth/layout logic without URL segments
Common Pitfalls
- Forgetting to register the router type (
declare module) - Not using
loaderDepswhen loader depends on search params (causes stale data) - Putting auth checks in components instead of
beforeLoad(flash of protected content) - Not handling the loading state with
pendingComponent - Using
useEffectfor data fetching instead of route loaders - Mutating search params directly instead of using navigate/Link
- Not wrapping the app with
RouterProvider - Forgetting
getParentRoutein code-based route definitions


