React 19 de Cero a Experto / Routing
Rutas protegidas y redirecciones
Casi toda app tiene zonas privadas: /perfil, /panel, /configuración —solo para usuarios
autenticados—. Un visitante sin sesión que intente entrar debe ser redirigido al login, y —detalle
que marca la calidad— tras loguearse, volver A DONDE QUERÍA IR. Eso son las RUTAS PROTEGIDAS. El patrón
es simple y elegante: un componente "guardia" que decide si renderiza la ruta o redirige. Hoy lo
construyes en vivo.
El portero de la zona VIP
Un guardia de rutas, en vivo
El patrón: un componente que recibe la ruta como children, comprueba la sesión, y renderiza el
contenido o redirige. Este playground lo demuestra con un login simulado (usa un mini-router propio para
correr sin dependencias, pero la LÓGICA del guardia es idéntica a la de React Router):
Sin sesión, RutaProtegida muestra el Login; al iniciar sesión, muestra el Perfil. La ruta
protegida (<Perfil>) no sabe nada de autenticación —el guardia decide por ella—. En React Router, en
vez de renderizar <Login> directamente, el guardia REDIRIGE a la ruta de login, como veremos ahora.
En React Router: Navigate y el destino
Con React Router, el guardia usa <Navigate> para redirigir, y guarda de dónde venía el usuario para
volver tras el login:
import { Navigate, useLocation } from "react-router-dom";
function RutaProtegida({ children }: { children: React.ReactNode }) {
const { usuario } = useAuth();
const location = useLocation();
if (usuario === null) {
// redirige al login, recordando a dónde iba (para volver luego).
// 'replace' evita que el atrás vuelva a la ruta protegida.
return <Navigate to="/login" replace state={{ volverA: location.pathname }} />;
}
return children;
}
// se usa envolviendo la ruta:
// <Route path="/perfil" element={<RutaProtegida><Perfil /></RutaProtegida>} />
// y en el login, tras autenticar:
function Login() {
const navegar = useNavigate();
const location = useLocation();
const volverA = location.state?.volverA ?? "/";
async function entrar() {
await auth.login();
navegar(volverA, { replace: true }); // vuelve a donde quería ir
}
// ...
}<Navigate to="/login" replace> redirige declarativamente (renderizarlo ES navegar). El replace
evita que la ruta protegida quede en el historial (si no, el botón atrás rebotaría entre login y ruta
protegida). Y el truco de calidad: guardar location.pathname en el state de la navegación, para que
el login sepa a dónde devolver al usuario tras autenticar. Sin eso, todos terminan en la home tras
loguearse, aunque quisieran ir a /gastos/5.
¿Cómo funciona una ruta protegida y por qué se usa 'replace' al redirigir al login?
Mini-reto
Amplía el playground: 1) agrega un segundo botón que alterne entre ver /perfil (protegida) y una
vista pública /inicio (siempre visible), y comprueba que el guardia solo bloquea /perfil; 2) muestra
un mensaje distinto en el login según de dónde venía el usuario (simula el volverA); 3) en un
comentario, explica por qué la ruta <Perfil> NO contiene ningún if de autenticación —dónde vive esa
lógica y por qué es mejor así—.
Qué sigue
Cierras el módulo construyendo tu PROPIO React Router en miniatura —rutas, <Link> y <Outlet>
funcionando en vivo con la History API—. Como con useQuery y Zustand, entenderás la librería por
dentro: es un Context que guarda la URL actual y unos componentes que la leen. La magia del routing,
desmitificada.