Esta guía detalla el proceso de configuración de TanStack Router en una Single Page Application (SPA) utilizando React y TypeScript. El objetivo es lograr un sistema de navegación robusto, con tipado fuerte y generación automática de rutas.
Demo en vivo: Explorar ejemplo desplegado "SPA_ejmTanStack"
El mismo ejemplo de enrutado pero desplegado sin SPA: NON-SPA_ejmTanStack
npm create vite@latest proyecto-remo -- --template react-ts
cd proyecto-remo
npm iAhora instalamos el TanStack Router y su plugin de Vite
npm install @tanstack/react-router @tanstack/router-plugin tslibrm -rf node_modules package-lock.json
npm install
npm run devEn vite.config.ts.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
export default defineConfig({
plugins: [
TanStackRouterVite(), // <- Aquí
react(),
],
})Ahora vamos a crear las rutas que es para lo que hemos hecho esto
mkdir src/routes.navbar {
display: flex;
gap: 20px;
padding: 20px;
background: white;
justify-content: center;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.nav-link {
text-decoration: none;
color: #333;
}
.nav-link.active {
font-weight: bold;
color: #007bff;
border-bottom: 2px solid #007bff;
}
.contenedor-principal {
padding: 40px;
font-family: sans-serif;
text-align: center;
}
.titulo-grande {
font-size: 3rem;
color: #1a1a1a;
}Este es el layout principal, es como van a salir todas las paginas.
En angular es el html del app, en el que cojemos el routerOulet con y elegimos la ruta con los routerLinks.
Aquí es el outlet y elegimos la ruta con los Links, si nos damos cuenta es lo mismo pero sin la palabra router delante.
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import '../estilos.css'
export const Route = createRootRoute({
component: () => (
<>
<nav className="navbar">
<Link to="/" className="nav-link">Inicio</Link>
<Link to="/club" className="nav-link">El Club</Link>
<Link to="/contacto" className="nav-link">Contacto</Link>
</nav>
<main className="contenedor-principal">
<Outlet />
</main>
</>
),
})import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: () => (
<div>
<h1 className="titulo-grande">PASIÓN Y TRADICIÓN</h1>
<p>Bienvenido al Club de Remo La Cala.</p>
</div>
),
})import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/club')({
component: () => (
<div>
<h2 className="titulo-grande">Nuestra Historia</h2>
<p>Somos vikingos desde 2002...</p>
</div>
),
})import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
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
}
}
ReactDOM.createRoot(document.getElementById('root')!).render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)npm run dev