Diego Vergara
Luis Angel Olivárez Estrada
Juan Pablo Bahos
Diego Vergara
Luis Angel Olivárez Estrada
Juan Pablo Bahos
Jhon Eduard Bocanegra Ortiz
SERGIO SAUL ROJAS VELASQUEZ
Brandon Argel Verdeja Domínguez
Andrés Esteban Rodríguez Jiménez
Ivan González
Samuel Miranda Martínez
FERNANDO ALBERTO RAMOS MARTINEZ
Juan Castro
Alvaro H. Ruiz V.
Santiago Pérez Sanabria
Jhon Jairo Gomez Calderon
Harold Zurita Simon
Juan Mercado
Ignacio Basilio
Alarcon Ricardo Ezequiel
Ing. Moisés Toro
Sebastian Carballo
Sebastian Hugo Sanchez
Nicolás García López
Gonzalo Gutiérrez Castillo
Daniel Alessandro García Batres
Charles Castillo Rosas
Remix Zapata
Mi solución
if(route.to == '/login' && auth.user){ return null }
Yo le pondría el "===" triple igual. Porque quizá si tenemos algún login con slug pueda causar error.
Yo también lo hice de esa manera.
Es un poco hardcode pero funciona :)
Para que no se pueda entrar directamente con url se debe crear un componente que envuelva las rutas privadas y dependiendo si ya hicieron login renderizarlas o no.
como haces este tipo de imagenes?
¡Hola, Sergio! Puedes sacar esas imágenes con la extensión CodeSnap. 😃
Menú con rutas públicas y privadas
Ahora vamos a hacer que nuestro menú no muestre los enlaces para hacer es crear las validaciones de si un usuario NO está registrado, no deberíamos mostrar una página de logout o perfil, y si está registrado, entonces no deberíamos mostrar la pestaña de login.
Para esto en nuestro menú debemos validar si tenemos un usuario registrado, o no:
Main.js
/* En cada una de nuestras rutas vamos a crear una nueva propiedad que se llame "private" que nos permita validár si cierta secciones pública o privada */ const routes = []; routes.push({ to: '/', text: 'Home', private: false, }); routes.push({ to: '/blog', text: 'Blog', private: false, }); routes.push({ to: '/profile', text: 'Profile', private: true, }); routes.push({ to: '/login', text: 'Login', private: false, }); routes.push({ to: '/logout', text: 'Logout', private: true, });
Teniendo esto ya podemos validar si renderizamos cierto componente o no lo hacemos; vamos entonces a crear la validación que nos permita lograr esto:
function Menu() { const auth = useAuth(); return ( <nav> <ul> {/* cambiamos el return inferido por unas llaves y el return */} {routes.map(route => { /* Este contenido se va a renderizar solo si se pasa la siguiente validación, si no estamos autenticados y tratamos de entrar a un a ruta privada entonces no vamos a renderizar esa ruta */ if (route.private && !auth.user) return null return ( <li key={route.to}> ... </li> ); })} </ul> </nav> ); }
Listo, ahora lo único de nos falta es que cuando estemos registrados, la manera que yo encontré es la siguiente:
function Menu() { ... return ( <nav> <ul> {routes.map(route => { ... /* Validamos si hay un usuario registrado, y si el nombre de la ruta es igual a Login entonces retornamos un "null" */ if (auth.user && route.text === 'Login') return null return ( <li key={route.to}> ... </li> ); })} </ul> </nav> ); }
Ahora lo único que nos falta es que no podamos acceder a las rutas por medio de la barra de búsqueda con Hashes, ya que si accedemos a una ruta que no se renderiza la aplicación se rompe.
Para solucionarlo simplemente agregué un segundo condicional después para saber si la ruta es Login y se está autenticado, quedarían así:
if(route.private && !auth.user) return null; if(route.text === 'Login' && auth.user) return null;
Amo como explica el profe ❤️❤️❤️
Hola profe JuanDc por fa cuéntame cual es el curso en donde me enseñan a manejar el sistema de autenticación??? Gracias
Excelente!!!!! Bueeenaaa Fernando!
Mi solución fue la siguiente:
if ((route.private && !auth.user) || (route?.publicOnly && !!auth.user)) return null;
De esta manera logré aplicar un solo condicional y reutilizar el código ya existente
Tenia un poco de dudas del funcionamiento de los return, pero cuando se manejan bien ahorras mucho código.
if (auth.user && route.text ==='Login') return null;
Menú con rutas públicas y privadas
.
Para simular tener rutas públicas y privadas en nuestro Menu, necesitamos añadir algunas propiedades a nuestro array de rutas.
.
primero agregamos la propiedad private para indicar si una ruta es privada o no. Luego a la ruta /login le añadimos la propiedad publicOnly que nos ayudará a ocultar esta ruta cuando estemos logueados pero siga siendo una ruta pública.
.
const routes = []; routes.push({ to: '/', text: 'Home', private: false, }); routes.push({ to: '/blog', text: 'Blog', private: false, }); routes.push({ to: '/profile', text: 'Profile', private: true, }); routes.push({ to: '/login', text: 'Login', private: false, publicOnly: true, }); routes.push({ to: '/logout', text: 'Logout', private: true, });
. Finalmente, agregamos 2 condicionales para que al momento de renderizar las rutas: .
.
import React from 'react'; import { NavLink } from 'react-router-dom'; import { useAuth } from './auth'; function Menu() { const auth = useAuth(); return ( <nav> <ul> {routes.map(route => { if (route.publicOnly && auth.user) return null; if (route.private && !auth.user) return null; return ( <li key={route.to}> <NavLink style={({ isActive }) => ({ color: isActive ? 'red' : 'blue', })} to={route.to} > {route.text} </NavLink> </li> ); })} </ul> </nav> ); } ... export { Menu };
.
Otra forma de renderizar las rutas sin tener que crear una propiedad publicOnly sería verificar si estamos logueados y la ruta corresponde a /login.
.
import React from 'react'; import { NavLink } from 'react-router-dom'; import { useAuth } from './auth'; function Menu() { const auth = useAuth(); return ( <nav> <ul> {routes.map(route => { if (!auth.user && route.private) return; if (auth.user && route.to === '/login') return; return ( <li key={route.to}> <NavLink style={({ isActive }) => ({ color: isActive ? 'red' : 'blue', })} to={route.to} > {route.text} </NavLink> </li> ); })} </ul> </nav> ); } const routes = []; routes.push({ to: '/', text: 'Home', private: false, }); routes.push({ to: '/blog', text: 'Blog', private: false, }); routes.push({ to: '/profile', text: 'Profile', private: true, }); routes.push({ to: '/login', text: 'Login', private: false, }); routes.push({ to: '/logout', text: 'Logout', private: true, }); export { Menu };
My solution
if(auth.user && route.text === 'Login') return null
No se si es la mas elegante de las soluciones, pero...
if (auth.user && route.text==="Login") return null
Esta fue mi solucion al reto de JuanDC:
{ routes.map(route => { if (route.private && !auth.user) return null if (auth.user && route.to.includes('login')) return null return ( <li key={route.to} > <NavLink style={({ isActive }) => ({ color: isActive ? 'red' : 'blue', })} to={route.to} end > { route.text} </NavLink> </li> ) }) }
Esta opción funcionará siempre y cuando la ruta del login incluya las palabras "login".
Escribiendo esto creo que la opción de Juan tiene mucho más sentido, pero bueno, esa se me ocurrió a mí.
Amo este profe
English version branch & commit
Branch name:
Commit message:
git commit -m "feat: implement basic protected route access control
- Add route protection based on authentication state
- Restrict access to sensitive pages for unauthenticated users
- Implement authentication checks in route components
- Add redirection for unauthorized access attempts"
La solución que implementé yo fue:
if(auth.user && route.to.includes("/login")) return null;
Pero la solución de Juan es mucho mas escalable para el futuro en caso de que quiera agregar muchas más rutas que sean sólamente publicas. Excelente!
if (route.publicOnly && auth.user) return null;
Mi solución fue agregar un nuevo condicional que valida si hay un usaurio logueado y si su ruta es la de login para evitar su renderización.
if(auth.user && (route.path === '/login')) return null ```if(auth.user && (*route*.path === '/login')) return null
Esta es otra forma de hacer el condicional:```js import React from "react"; import { NavLink } from "react-router-dom"; import { useAuth } from "../auth";
function Menu() { const auth = useAuth();
const routes = [ { to: "/", text: "Home", private: false }, { to: "/blog", text: "Blog", private: false }, { to: "/profile", text: "Profile", private: !auth.user }, { to: "/login", text: "Login", private: !!auth.user }, { to: "/logout", text: "Logout", private: !auth.user }, ];
return ( <nav> <ul> {routes.map((route) => { if (route.private) return null;
return ( <li key={route.to}> <NavLink style={({ isActive }) => ({ color: isActive ? "red" : "blue", })} to={route.to} > {route.text} </NavLink> </li> ); })} </ul> </nav>
); }
export { Menu };
Mis apuntes en Notion💚
Para solucionar el problema de que pongan la ruta /profile y no haya iniciado sesión, usé esta estrategia:
En ProfilePage.jsx
import { useNavigate } from 'react-router-dom'; import { useAuth } from '../../auth/useAuth'; import { useEffect } from 'react'; export const ProfilePage = () => { const { user } = useAuth(); const navigate = useNavigate(); useEffect(() => { if (user === null) return navigate('/login'); }); return ( <div> <h3>Profile</h3> <p>Welcome, {user?.username}!</p> </div> ); };