TanStack Router is the fully type-safe React router that makes React Router look like it's from 2015. Search params, loaders, and route context — all with full TypeScript inference.
The Free APIs You're Missing
1. Type-Safe Search Params — No More useSearchParams
import { createFileRoute } from "@tanstack/react-router";
import { z } from "zod";
export const Route = createFileRoute("/products")(
validateSearch: z.object({
page: z.number().default(1),
sort: z.enum(["price", "name", "date"]).default("date"),
category: z.string().optional(),
minPrice: z.number().optional(),
}),
});
// In component — fully typed!
function ProductsPage() {
const { page, sort, category } = Route.useSearch();
const navigate = Route.useNavigate();
return (
<button onClick={() => navigate({ search: { page: page + 1 } })}>
Next Page
</button>
);
}
2. Route Loaders — Data Fetching Before Render
export const Route = createFileRoute("/users/$userId")({
loader: async ({ params }) => {
const user = await fetchUser(params.userId);
const posts = await fetchPosts(params.userId);
return { user, posts };
},
component: UserPage,
});
function UserPage() {
const { user, posts } = Route.useLoaderData();
// Data is already loaded — no loading states!
return <div>{user.name} has {posts.length} posts</div>;
}
3. Route Context — Dependency Injection for Routes
const router = createRouter({
routeTree,
context: {
auth: undefined!, // Will be provided
queryClient: undefined!,
},
});
export const Route = createFileRoute("/admin")({
beforeLoad: ({ context }) => {
if (!context.auth.isAdmin) throw redirect({ to: "/login" });
},
loader: ({ context }) => {
return context.queryClient.ensureQueryData(adminStatsQuery);
},
});
4. Pending UI — Automatic Loading States
function App() {
return (
<RouterProvider
router={router}
defaultPendingComponent={() => <Spinner />}
defaultErrorComponent={({ error }) => <ErrorPage error={error} />}
defaultNotFoundComponent={() => <NotFound />}
/>
);
}
5. Path Params — Fully Typed
// routes/users/$userId/posts/$postId.tsx
export const Route = createFileRoute("/users/$userId/posts/$postId")({
component: PostPage,
});
function PostPage() {
const { userId, postId } = Route.useParams();
// Both are typed as string — no manual parsing
}
// Navigation is type-safe too
<Link to="/users/$userId/posts/$postId" params={{ userId: "123", postId: "456" }}>
View Post
</Link>
Getting Started
npm install @tanstack/react-router
Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com
Check out my awesome-web-scraping list for the best scraping tools and resources.
Top comments (0)