TanStack Router is the first fully type-safe router for React. Search params, path params, loaders — everything is typed end-to-end.
Type-Safe Route Tree
import { createRootRoute, createRoute, createRouter } from "@tanstack/react-router";
const rootRoute = createRootRoute({ component: RootLayout });
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/",
component: HomePage,
});
const productRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/products/$productId",
// Loader runs before render — type-safe!
loader: async ({ params }) => {
return fetchProduct(params.productId); // params.productId is typed as string
},
component: ProductPage,
});
function ProductPage() {
const { productId } = productRoute.useParams(); // Typed!
const product = productRoute.useLoaderData(); // Typed!
return <div>{product.title}</div>;
}
Type-Safe Search Params
import { z } from "zod";
const productsRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/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(),
}),
component: ProductsPage,
});
function ProductsPage() {
const { page, sort, category } = productsRoute.useSearch(); // All typed!
const navigate = productsRoute.useNavigate();
return (
<button onClick={() => navigate({ search: (prev) => ({ ...prev, page: prev.page + 1 }) })}>
Next Page
</button>
);
}
Pending UI + Stale-While-Revalidate
const route = createRoute({
path: "/data",
loader: ({ context }) => context.queryClient.ensureQueryData(dataQuery),
pendingComponent: () => <Skeleton />,
errorComponent: ({ error }) => <ErrorView error={error} />,
staleTime: 30_000, // Show stale data for 30s while revalidating
});
File-Based Routing
src/routes/
__root.tsx → Root layout
index.tsx → /
about.tsx → /about
products/
index.tsx → /products
$productId.tsx → /products/:productId
$productId.edit.tsx → /products/:productId/edit
Devtools
import { TanStackRouterDevtools } from "@tanstack/router-devtools";
function RootLayout() {
return (
<>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
</>
);
}
Building data-driven apps? My Apify tools feed structured data into your TanStack-powered routes.
Custom solution? Email spinov001@gmail.com
Top comments (0)