Contenido del curso

Rutas protegidas con Navigate en React

Resumen

Proteger rutas privadas en React con React Router Dom va más allá de ocultar enlaces del menú: necesitas redirigir al usuario cuando intente acceder por URL a una página que requiere autenticación. Aquí aprendes a crear protected routes reutilizables y a manejar también rutas public only como el login.

Por qué ocultar el menú no protege tus rutas en React

Cuando un usuario adivina o recuerda una URL, React Router Dom sigue renderizando el componente aunque el enlace no esté visible. Eso significa que rutas como /login, /profile o /logout quedan accesibles si solo las quitaste del menú.

La solución real es redirigir al usuario según su estado de autenticación: si entra a /profile sin sesión, mándalo a /login; si ya está autenticado y entra a /login, mándalo a /profile.

¿Qué es una protected route? Es una ruta que valida si el usuario cumple una condición de autenticación antes de renderizar su contenido. Si no la cumple, redirige a otra página usando un componente como Navigate.

Cómo hacer un redirect con el componente Navigate de React Router

React Router expone el componente Navigate (con N mayúscula) que recibe una propiedad to para enviar al usuario a otra ruta. Funciona como cualquier componente JSX, pero su efecto es navegar [02:30].

La primera versión, dentro del propio ProfilePage, se ve así:

jsx import { Navigate } from "react-router-dom"; import { useAuth } from "./auth";

function ProfilePage() { const auth = useAuth();

if (!auth.user) { return <Navigate to="/login" />; }

return <h1>Hola {auth.user.username}</h1>; }

Un detalle clave: tienes que retornar el Navigate. Sin el return, el componente nunca se renderiza y el código sigue intentando leer auth.user.username, lo que dispara el error cannot read username of null [03:40].

Por qué repetir esta lógica en cada página no escala

Funciona, sí, pero si tienes diez rutas privadas vas a copiar el mismo if diez veces. Ahí entra la idea de extraer un componente reutilizable.

Cómo crear un componente AuthRoute reutilizable

La convención en la industria es nombrarlo AuthRoute, ProtectedRoute o PrivateRoute. Su trabajo es validar la sesión una sola vez y renderizar props.children solo si pasa la validación.

jsx import { Navigate } from "react-router-dom"; import { useAuth } from "./auth";

export function AuthRoute(props) { const auth = useAuth();

if (!auth.user) { return <Navigate to="/login" />; }

return props.children; }

Aquí aparece el patrón de children as props: el componente envuelve a otros y decide si los muestra o no. Pero hay una trampa cuando lo usas mal.

Por qué AuthRoute falla si lo usas dentro de la propia página

Si envuelves el JSX de ProfilePage con <AuthRoute> desde dentro del mismo componente, React aún intenta evaluar auth.user.username antes de que AuthRoute haga el redirect, y vuelve el error de lectura sobre null.

Un parche rápido es usar optional chaining: auth.user?.username devuelve undefined en vez de explotar. Equivale a preguntar manualmente si auth.user existe antes de leer la propiedad.

¿Qué hace el operador ?. en JavaScript? Si el valor antes del ?. es null o undefined, devuelve undefined en vez de lanzar error. Es la forma corta de un condicional defensivo.

Funciona, pero no es la mejor opción. La solución limpia es mover la protección al árbol de rutas.

Cómo proteger rutas desde el componente App con AuthRoute

En lugar de envolver el JSX dentro de cada página, envuelve el componente página directamente en la definición de la ruta dentro de App.js. Así la página solo se monta cuando la validación pasa, y puedes asumir que auth.user siempre existe.

jsx <Route path="/profile" element={ <AuthRoute> <ProfilePage /> </AuthRoute> } /> <Route path="/logout" element={ <AuthRoute> <LogoutPage /> </AuthRoute> } />

Con esto, ProfilePage ya no necesita importar Navigate ni validar nada. Si entras a /profile sin sesión, AuthRoute te manda a /login antes de que se monte la página [09:50].

La misma lógica aplica a /logout: no tiene sentido cerrar sesión sin haberla iniciado, y ahora queda protegida con el mismo componente.

Cómo hacer una ruta public only para el login

Falta el caso inverso: si ya estás autenticado, no deberías ver /login. Podrías crear un NoAuthRoute simétrico, pero si solo tienes una página en esta situación, basta con resolverlo dentro de LoginPage.

jsx function LoginPage() { const auth = useAuth();

if (auth.user) { return <Navigate to="/profile" />; }

return <LoginForm />; }

Si entras manualmente a /login con sesión activa, te redirige al perfil. Crear un componente dedicado tiene sentido cuando tienes varias rutas public only; con una sola, la validación inline es suficiente.

Qué estrategias de protección de rutas existen en React

A lo largo del flujo aparecieron tres formas de resolver el mismo problema, cada una con su trade off:

  • Validación inline dentro del componente página, útil para casos puntuales pero repetitiva.
  • Componente AuthRoute envolviendo el JSX desde dentro, requiere optional chaining y no es tan limpio.
  • Componente AuthRoute aplicado en la definición de rutas en App.js, la opción más escalable y la que mejor developer experience ofrece.

La elección correcta depende de cuántas rutas privadas tengas y de qué tan limpio quieras mantener cada componente página.

Con esto tu sistema de navegación queda completo: rutas privadas con redirect a login, rutas public only con redirect a perfil, y un patrón reutilizable. El siguiente paso natural es la autorización por roles, decidir qué puede hacer cada usuario autenticado según sus permisos.

¿Cómo nombras tú estos componentes en tus proyectos: AuthRoute, ProtectedRoute o PrivateRoute? Cuéntalo en los comentarios.