CodeForge

React 19 de Cero a Experto / Routing

Rutas protegidas y redirecciones

Teoría22 min20 XP

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:

ruta-protegida-router.tsx
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.