React
React Router: rutas, layouts y navegación
Explica cómo definir rutas, layouts anidados, parámetros, enlaces, navegación programática y estados de ubicación con React Router.
- Última actualización
- Actualizada
- Nivel
- Aplicación
React
Explica cómo definir rutas, layouts anidados, parámetros, enlaces, navegación programática y estados de ubicación con React Router.
React Router relaciona la URL con un árbol de interfaz. Permite que navegación, parámetros y layouts formen parte del estado compartible de la aplicación.
import { BrowserRouter, Route, Routes } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductsPage />} />
<Route path="/products/:productId" element={<ProductPage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
);
}<Link to={`/products/${product.id}`}>{product.name}</Link>Usa Link o NavLink para navegación iniciada por el usuario. Conservan comportamiento de enlace, historial y apertura en otra pestaña.
function ProductPage() {
const { productId } = useParams();
return <ProductDetails productId={productId!} />;
}Los parámetros llegan como strings y deben validarse antes de usarse.
<Route path="dashboard" element={<DashboardLayout />}>
<Route index element={<Overview />} />
<Route path="orders" element={<Orders />} />
</Route>function DashboardLayout() {
return (
<>
<DashboardNavigation />
<main><Outlet /></main>
</>
);
}<NavLink
to="/products"
className={({ isActive }) => isActive ? "active" : undefined}
>
Productos
</NavLink>El estado activo debe acompañarse de estructura visual y accesible apropiada.
const navigate = useNavigate();
async function handleSave() {
const order = await createOrder();
navigate(`/orders/${order.id}`, { replace: true });
}Úsala después de acciones o decisiones programáticas. No reemplaces enlaces normales por botones que llaman navigate.
Una comprobación cliente puede redirigir por UX, pero el backend sigue validando acceso a cada recurso y operación.
Search params son adecuados para filtros, búsqueda, página o tabs que deben sobrevivir recarga y compartirse.
useNavigate para cualquier enlace.productId como dato ya validado.useState.El router no solo intercambia páginas: modela una parte del estado de la aplicación mediante URLs, layouts e historial.
La documentación moderna organiza React Router en tres modos acumulativos:
Declarative
→ matching, Link, NavLink, location y navigate
Data
→ route objects, loaders, actions, pending y fetchers
Framework
→ módulos de ruta, build plugin, SSR/prerender y convenciones completasNo mezcles ejemplos sin indicar el modo. Una SPA pequeña puede usar Declarative. Una aplicación que necesita carga y mutaciones coordinadas puede usar Data. Framework Mode añade una arquitectura más completa con tooling propio.
En instalaciones modernas, las APIs principales se importan desde react-router y algunas integraciones DOM específicas desde react-router/dom:
import { BrowserRouter, Routes, Route } from "react-router";import { createBrowserRouter } from "react-router";
import { RouterProvider } from "react-router/dom";react-router-dom continúa apareciendo en proyectos v6/v7 y rutas de migración, pero una nota vigente debe comprobar la versión y modo del proyecto antes de copiar imports.
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="products" element={<ProductsLayout />}>
<Route index element={<ProductList />} />
<Route path=":productId" element={<ProductDetail />} />
</Route>
</Routes>
</BrowserRouter>
);
}Este modo relaciona URL y elementos, pero tú diseñas data fetching, errors y pending.
const router = createBrowserRouter([
{
path: "/products/:productId",
loader: productLoader,
action: productAction,
element: <ProductRoute />,
errorElement: <RouteError />,
},
]);Crea el router fuera del árbol para mantener una instancia estable. Loaders pueden iniciar datos antes del componente, Actions modelan mutaciones y el router coordina revalidación.
Las rutas se convierten en módulos con tipos, loaders, actions, pending, error y estrategias de rendering. Puede funcionar como SPA, SSR o prerender según configuración. No es “React base”; añade plugin, servidor y convenciones del framework React Router.
const [params, setParams] = useSearchParams();
const query = params.get("query") ?? "";
const page = Number(params.get("page") ?? "1");Usa URL para estado que debe:
No guardes objetos grandes, secretos ni estado efímero de hover.
const { productId } = useParams();
if (!productId || !isValidProductId(productId)) {
return <NotFound />;
}Los params y search params son input externo. Valida tipo, rango y permisos. Un route match no garantiza que la entidad exista.
Link representa navegación y conserva abrir en pestaña, copiar destino y comportamiento del historial.
<Link to={`/products/${product.id}`}>{product.name}</Link>useNavigate es apropiado después de una Action, timeout o decisión programática. No sustituyas cada enlace por un botón.
function DashboardLayout() {
return (
<div>
<DashboardNavigation />
<main>
<Outlet />
</main>
</div>
);
}Un layout comparte estructura, providers y boundaries. Decide si su state debe preservarse entre rutas hijas.
En Data/Framework Mode, loaders de rutas coincidentes pueden ejecutarse coordinadamente y, según estrategia, en paralelo. Esto evita que cada componente espere a montarse para descubrir sus datos.
No hagas el mismo fetch otra vez en un effect si el loader ya es la fuente de la ruta.
Una route action procesa mutaciones y el router puede revalidar loaders relacionados después:
<Form method="post">
<input name="title" />
<button>Crear</button>
</Form>El servidor sigue validando, autorizando e implementando idempotencia.
Diseña límites donde la navegación pueda mostrar feedback sin borrar toda la aplicación. Data/Framework Mode ofrecen estado de navegación, errores de ruta y fetchers para mutaciones sin navegación.
Un loader cliente o redirect mejora UX, pero la autoridad vive en servidor. En Framework Mode, un loader servidor puede verificar sesión antes de devolver datos; cada action vuelve a autorizar.
Después de navegar:
El router no hace accesible cualquier transición automáticamente.
Usa routers de memoria o stubs del modo elegido. Prueba:
Navegación avanzada y carga diferida conecta loaders, Actions, fetchers, boundaries y división de código.