TanStack Router: Roteamento Type-First
Aula 2 de 5
Roteamento com TanStack Router
O TanStack Router é um roteador type-safe com suporte a file-based routing, loaders, componentes de loading/error e validação de parâmetros.
Configuração Inicial
npm create vite@latest router-demo -- --template react-ts
cd router-demo
npm install @tanstack/react-router
Estrutura de Rotas
// src/main.tsx — Provider e Router
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
const router = createRouter({ routeTree })
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
function App() {
return <RouterProvider router={router} />
}
createRootRoute e Layout
// src/routes/__root.tsx
import { createRootRoute, Outlet, Link } from '@tanstack/react-router'
export const Route = createRootRoute({
component: () => (
<div>
<nav>
<Link to="/" className="[&.active]:font-bold">Home</Link>
<Link to="/dashboard" activeProps={{ className: 'font-bold' }}>Dashboard</Link>
</nav>
<hr />
<Outlet /> {/* Renderiza o conteúdo da rota filha */}
</div>
),
})
Rotas com Parâmetros
// src/routes/users.$userId.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/users/$userId')({
component: UserProfile,
loader: async ({ params }) => {
const user = await fetch(`/api/users/${params.userId}`).then(r => r.json())
return { user }
},
pendingComponent: () => <div>Carregando...</div>,
errorComponent: ({ error }) => <div>Erro: {error.message}</div>,
})
function UserProfile() {
const { user } = Route.useLoaderData()
const { userId } = Route.useParams()
return <div>{user.name}</div>
}
Search Params com Validação
// src/routes/users/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const searchSchema = z.object({
page: z.number().default(1),
search: z.string().optional(),
sort: z.enum(['name', 'date']).default('name'),
})
export const Route = createFileRoute('/users/')({
validateSearch: (search: Record<string, unknown>) => searchSchema.parse(search),
component: UserList,
})
function UserList() {
const { page, search, sort } = Route.useSearch()
const navigate = Route.useNavigate()
return (
<div>
<input
value={search}
onChange={e => navigate({ search: { search: e.target.value, page: 1 } })}
/>
<UsersTable page={page} search={search} sort={sort} />
</div>
)
}
Route Guards e Redirect
export const Route = createFileRoute('/dashboard')({
beforeLoad: async ({ location }) => {
const token = localStorage.getItem('token')
if (!token) {
throw redirect({ to: '/login', search: { redirect: location.href } })
}
},
component: Dashboard,
})
Navegação Programática
// useNavigate hook
const navigate = useNavigate()
navigate({ to: '/users/$userId', params: { userId: '123' } })
navigate({ to: '/', search: { q: 'termo' } })
navigate({ to: '.', search: { page: current + 1 } }) // relativo
Lab: Aplicação Multi-rota
npm create vite@latest router-app -- --template react-ts
cd router-app
npm install @tanstack/react-router
npx tsr generate
// Crie:
// 1. Rota raiz com layout e navegação
// 2. /products com search params (paginação, filtro)
// 3. /products/$productId com loader assíncrono
// 4. Rota protegida /admin com beforeLoad guard
// 5. Componente pending e error para cada rota
O TanStack Router oferece type-safety total entre links, parâmetros e loaders, eliminando inconsistências comuns em roteadores tradicionais.