You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
4 Hrs
43 Min
12 Seg

Menú con rutas públicas y privadas

12/30
Resources

How do you improve navigation depending on the authentication status?

When building web applications one of the crucial steps is to handle authentication and authorization properly. In this session, we focus on improving the navigation of our application so that it adapts to the state of the user: whether they are authenticated or not. This ensures that users only see relevant paths and pages based on their current session.

What bug did we fix when adjusting the paths?

In the previous class, we developed a basic authentication system that, while functional, had a navigation error. The goal here is to ensure that our menu does not display login or logout options inconsistently. We want, for example, the option for "login" to disappear if the user is already logged in, and the "profile" option not to be visible if the user is not authenticated. Here is the solution:

  1. Add 'private' property to routes:
    • All routes should default to private property : false.
    • Exceptions are paths like profile, which should be marked as private: true so that the system is able to not show these pages if the user is not authenticated.

How to control the visibility of private paths?

To keep track of the user's session state, we use a React Hook known as useAuth. This provides us with vital information on whether the user is currently logged in, which allows us to condition the rendering of routes based on this state.

import { useAuth } from './useAuth';
// In the menu componentif (route.private && !auth.user) { return null;}
  • Hook functions useAuth:
    • auth.user: this object contains user information if logged in and is null otherwise.
    • Thanks to this we can prevent the rendering of private routes when there is no authenticated user.

How do we improve the logic for public routes?

Once the private routes are handled, the next thing is to not show the routes as the login if the user is already authenticated. For this, we label these routes as publicOnly, which also causes them not to be rendered if the user is already logged in.

if (route.publicOnly && auth.user) { return null;}
  • This ensures that if the user is already authenticated, the pages intended for registration or login are not visible.

What else can we optimize?

The implementation also contemplates the possibility of adding additional logic to handle inconsistent states where the user manually changes the URL to access paths that should be protected according to their authentication status. This handling, of course, requires additional configurations on the backend server to be completely secure.

Employing these practices not only provides a better user experience, but also helps to maintain the integrity and security of our application. Now, I encourage you to implement and adjust these practices to your current or future projects!

Contributions 66

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

Mi solución

          if(route.to == '/login' && auth.user){
            return null
          }

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.

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 ❤️❤️❤️

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:
.

  • Si la ruta es privada y no estamos logueados, entonces no se renderiza la ruta.
  • Si la ruta es solo pública y estamos logueados, entonces no se renderiza la ruta.

.

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í.

**English version branch & commit** <https://github.com/SebaMat3/react-router-course-p1/tree/feat/set-private-routes> **Branch name:** * feat/set-private-routes **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. ```js 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>
    {routes.map((route) => { if (route.private) return null; return (
  • <NavLink style={({ isActive }) => ({ color: isActive ? "red" : "blue", })} to={route.to} > {route.text} </NavLink>
  • ); })}
</nav> ); } export { Menu }; ```

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>
      <h2>Profile</h2>
      <p>Welcome, {user?.username}!</p>
    </div>
  );
};

jajajaja me gusta más tu solución, xD yo estaba haciendo una función para que cuando se return - el estado private de login cambiara a true - ya iban 11 líneas de código 😣🙄

Yo el último reto lo resolví con useEffect.

Login:

    React.useEffect(()=>{
        if(auth.user){
            return navigate('/');
        }
    },[auth.user]);

Logout:

    React.useEffect(()=>{
        if(!auth.user){
            return navigate('/login')
        }
    },[auth.user]);

yo lo había hecho así

if(route.to === '/login' && auth.user) {
         return (route.private = true)
} else {route.private = false}

Buenas, aqui dejo mi solucion a el problema de mostrar unicamente el login cuando no se este logeado un usuario

My solution

Mi solución

if (route.private === "out" && auth.user) return null;
let routes = [
  {
    to: "/",
    text: "Home",
    private: "both",
  },
  {
    to: "/blog",
    text: "Blog",
    private: "both",
  },
  {
    to: "/profile",
    text: "Profile",
    private: "in",
  },
  {
    to: "/login",
    text: "Login",
    private: "out",
  },
  {
    to: "/logout",
    text: "Logout",
    private: "in",
  },
];

yo lo hice de esta forma sin necesidad de añadir las propiedades private y publicOnly al arreglo de objetos

if (!user && (route.to === '/profile' || route.to === '/logout')){
    return 
}

if (user && route.to === '/login'){
    return 
}

Mi solución al reto

mi solución

<code> 
<ul className="nav">    
            <li className="nav-item">
                {routes.map(route => 
                    (
                        (user && !route.publicOnly) || (!user && !route.private) ? 
                        <NavLink 
                            key={route.to}
                            to={route.to}
                            className={({isActive})=>(`nav-link ${isActive? 'active' : ''}`)}
                        >
                            {route.text}
                        </NavLink> : null
                    )
                )}
            </li>
        </ul>
if((route.private && !auth.user) || (route.to === '/login' && auth.user)) return null;


La solucion que hice:

if(auth.user && route.text === "Login") return null;

Hola, Comunidad 🚀

Mi solución es la siguiente; no sé si tenga algún problema más adelante pero pensando desde ahora no lo creo.

if (route.textContext === 'Login' && auth.user) return null;

// Mi arreglo con los objetos 👇👇

const routes = [];
routes.push({
  id: 1,
  to: '/',
  textContent: 'Home',
  private: false,
});

routes.push({
  id: 2,
  to: '/blog',
  textContent: 'Blog',
  private: false,
});

routes.push({
  id: 3,
  to: '/profile',
  textContent: 'Profile',
  private: true,
});
routes.push({
  id: 4,
  to: '/login',
  textContent: 'Login',
  private: false,
});
routes.push({
  id: 5,
  to: '/logout',
  textContent: 'Logout',
  private: true,
});

Si hay algún problema, estoy dispuesto a escuchar feedback.

Saludos.

Pensando en el caso de Freddy que es un superadmin, debería tener rutas que solo el puede entrar.

Por esa razon cambie lo de public y private por un route type, para que no nos crezca de manera vertical el objeto al agregar otro typo de ruta.

const Menu = () => {
  const auth = useAuth();

  return (
    <nav>
      <ul>
        {routes.map((route) => {
          if (route.routeType === routeTypes.private && !auth.user) return null;
          if(route.routeType === routeTypes.onlyPublic && auth.user) return null
          return (
            <li key={route.to}>
              <NavLink to={route.to}>{route.text}</NavLink>
            </li>
          );
        })}
      </ul>
    </nav>
  );
};
const routeTypes = {
    private: 'PRIVATE',
    onlyPublic: '0NLY-PUBLIC',
    all:'ALL'
}

const routes = [];
routes.push({
  routeType: routeTypes.all,
  to: "/",
  text: "Home",
});
routes.push({
routeType: routeTypes.private,
  to: "/profile",
  text: "Profile",
});
routes.push({
  routeType: routeTypes.all,
  to: "/blog",
  text: "Blog",
});
routes.push({
  routeType: routeTypes.onlyPublic,
  to: "/login",
  text: "Login",
});
routes.push({
  routeType: routeTypes.private,
  to: "/logout",
  text: "Logout",
});

Mi practica

import React from 'react';
import {NavLink} from "react-router-dom";
import routes from '../fixtures/routes';
import {useAuth} from "./auth/auth";

function Menu() {
    const auth = useAuth();
    const checkIsActive = (active) => {
        return {color: (active) ? 'green' : 'red'};
    };
    const isOnlyPublicRoute = (route) => {
        return !(route?.onlyPublic && auth.user);
    };
    const isPrivateRoute = (route) => {
        return !(route.private && !auth.user);
    };

    return (
        <nav>
            <ul>
                {
                    routes.map(route => {
                        if (isOnlyPublicRoute(route)) {
                            if (isPrivateRoute(route)) {
                                return (<li key={route.id}>
                                    <NavLink
                                        to={route.to}
                                        end
                                        style={({isActive}) => (checkIsActive(isActive))}
                                    >
                                        {route.text}
                                    </NavLink>
                                </li>);
                            }
                        }
                    })
                }

            </ul>
        </nav>
    );
}

export {Menu};

A mi se me ocurrio esto y funciono. =)

Yo había intentando hacer push a según que ruta dependiendo de si estamos autentificados o no. El problema es que el render no cambia ya que el array tampoco lo hace.
Las soluciones de los comentarios sobre comprobar directamente si la ruta es login no me parecen convenientes. Si queremos cambiar algo de esa ruta en algún momento, tendríamos que cambiar también el condicional.
Finalmente decidí agregar una propiedad ‘onlyIfNotAuth’ a login (no la cambié porque creo que el nombre ‘publicOnly’ es confuso).

Mi solución:

else if (route.to === '/login' && auth.user?.username) return null;

Mi solución:

if (auth.user && route.to === '/login') return null;
          if (route.to !== "/login" && auth.user) {
            return (
              <li key={route.to}>
                <NavLink
                  style={({ isActive }) => ({
                    color: isActive ? "red" : "blue",
                  })}
                  to={route.to}
                >
                  {route.text}
                </NavLink>
              </li>
            );
          }

Para mi fue simple y obvio

if (route.text === 'Login' && auth.user) return null
function Menu() {
  const auth = useAuth();
  return (
    <NavLink>
      {routes.map((route) => {
        if (route.private && !auth.isUsernameLog) return null;
        return (
          <ul>
            {auth.isUsernameLog && route.to === "/login" ? null : (
              <li>
                <Link to={route.to}>{route.title}</Link>
              </li>
            )}
          </ul>
        );
      })}
    </NavLink>
  );
}```

Con el ultimo challenge

function Menu() {
  const auth = useAuth();
  const location = useLocation();
  const navigate = useNavigate();

  return (
    <NavLink>
      {routes.map((route) => {
        if (route.private && !auth.isUsernameLog) return null;
        if (location.pathname === "/login" && auth.isUsernameLog)
          return navigate("/profile");
        if (location.pathname === "/profile" && !auth.isUsernameLog)
          return navigate("/");
        return (
          <ul>
            {auth.isUsernameLog && route.to === "/login" ? null : (
              <li>
                <Link to={route.to}>{route.title}</Link>
              </li>
            )}
          </ul>
        );
      })}
    </NavLink>
  );
}

Creo que la forma mas sencilla es invertir la condicional y funciona de marivilla.

{authentications.map((authentication) => {
          if (authentication.private && !auth.user) return null;
          if (!authentication.private && auth.user) return null;
          return (
            <li>
              <NavLink to={authentication.to}>{authentication.text}</NavLink>
            </li>
          );
        })}

#setotea

Creo que no fue lo mas eficiente, pero a mi me funciono de esta forma jejejee

const Menu = () => {
  const { auth } = useAuth();
  return (
    <nav>
      <ul className=''>
        {routes.map((route, index) => {
          if (!route.private && !auth?.username) {
            return <MenuItem key={route.text} route={route} />;
          }
          if (route.private && auth?.username) {
            return <MenuItem key={route.text} route={route} />;
          }
        })}
      </ul>
    </nav>
  );
};

Para el reto coincidí con el profesor y lo resolví de la misma forma, pero también se me ocurrieron otras:

if( route.text === 'Login' && auth.user ) return null;

O también:

if( route.to === '/login' && auth.user ) return null;

Aunque a mi parecer estas son menos dinámicas, ya que si se cambia el nombre o la ruta, habrá que hacer el cambio en el condicional también.

```js export const Menu = () => { const { user } = useAuth(); const isAuthenticated = !!user; const isLoginPage = (route: RouteItem) => route.to === '/login'; const isNavLinkActive = ({ isActive }: { isActive: boolean }) => ({ color: isActive ? 'red' : 'blue', }); return (
    {routes .filter((route) => isAuthenticated ? isAuthenticated && !isLoginPage(route) : !route.private) .map(({ to, label }) => (
  • <NavLink key={to} style={isNavLinkActive} to={to}> {label} </NavLink>
  • ))}
); }; ```
Yo creo que la solución más sencilla para lo del Login y Logout es tener un solo item y cambiar su nombre de Login -> Logout cuando este autenticado.
En mi caso lo que hice, en resumen, fue: En auth: 1. Anadir a isAuthenticated y isLoggedIn para verificar como si fueran tokens. 2. Cree una funcion llamada PrivateRoute, en caso de que no haya un usuario autenticado, va a redirigir a login, cuando se ponga en uso esta funcion en las rutas que se quiere que sean privadas y requieran de autenticacion, sino que retorne el contenido de la ruta sin problemas. De esta manera queda auth: ![](https://static.platzi.com/media/user_upload/image-16746166-73c1-4895-93ca-1ee14700da15.jpg) Para el caso del login solamente anadi una sencilla condicion, cuando no haya un usuario logeado, se muestra el formulario o de lo contrario, siempre retorna al home '/'. Aqui la pagina de login: ![](https://static.platzi.com/media/user_upload/image-ceedcea9-d98e-44b3-a2e9-3073c4142885.jpg) En el app.js, en mi caso main.jsx, queda de la siguiente manera: ![](https://static.platzi.com/media/user_upload/image-6a4583cb-d275-4570-adda-7b657c405231.jpg) La ruta de profile queda envuelta antes en el componente PrivateRouter, sirviendo como middleware impidiendo el acceso si no hay un usuario autenticado. En el menu, tambien hice solo una condicion para que cuando haya un usuario logeado solo muestre el menu el logout, y si no hay un usuario logeado, muestre el login. Aqui el menu: ![](https://static.platzi.com/media/user_upload/image-07353843-cca1-4220-b606-e5be8f5d6693.jpg)
Esto fue lo que hice en el reto, no me gustó pero quedó: ```ts import React from 'react'; // import { Link, NavLink } from 'react-router-dom' import { NavLink } from 'react-router-dom' import { useAuth } from './../hooks/auth' const Menu: React.FC = () => { const auth:any = useAuth(); const routes = [] routes.push( { to: '/', text: 'Home', private: false, }, { to: '/blog', text: 'Blog', private: false, }, { to: '/login', text: 'Login', private: false, }, { to: '/profile', text: 'Profile', private: true, }, { to: '/logout', text: 'Logout', private: true, }, ) return( <> <nav className='menu__Nav'>
    { !auth.user ? ( routes.map((route, index) => (
  • { !route.private && !auth.user ? ( <NavLink // className={({ isActive }) => ''} style={({ isActive }) => ({ color: isActive ? 'blue' : 'purple' })} to={route.to} > {route.text} </NavLink> ) : ( <> ) }
  • ) )) : ( routes.map((route, index) => (
  • { route.text === 'Login' ? ( <> ) : ( <NavLink // className={({ isActive }) => ''} style={({ isActive }) => ({ color: isActive ? 'blue' : 'purple' })} to={route.to} > {route.text} </NavLink> ) }
  • ) ))}
</nav> ) } export { Menu } ```
```txt import React from 'react'; // import { Link, NavLink } from 'react-router-dom' import { NavLink } from 'react-router-dom' import { useAuth } from './../hooks/auth' const Menu: React.FC = () => { const auth:any = useAuth(); const routes = [] routes.push( { to: '/', text: 'Home', private: false, }, { to: '/blog', text: 'Blog', private: false, }, { to: '/login', text: 'Login', private: false, }, { to: '/logout', text: 'Logout', private: true, }, { to: '/profile', text: 'Profile', private: true, } ) return( <> <nav className='menu__Nav'>
    {routes.map((route, index) => (
  • { route.private && !auth.user ? ( <> ) : ( <NavLink // className={({ isActive }) => ''} style={({ isActive }) => ({ color: isActive ? 'blue' : 'purple' })} to={route.to} > {route.text} </NavLink> ) }
  • ))}
</nav> ) } export { Menu } ```
`import React from 'react';// import { Link, NavLink } from 'react-router-dom'import { NavLink } from 'react-router-dom'import { useAuth } from './../hooks/auth'` `const Menu: ``React``.``FC`` = () => {` `    const auth:``any`` = useAuth();` `    const routes = []` `    routes.push(        {            to: '/',            text: 'Home',            private: false,        },        {            to: '/blog',            text: 'Blog',            private: false,        },        {            to: '/login',            text: 'Login',            private: false,        },        {            to: '/logout',            text: 'Logout',            private: true,        },        {            to: '/profile',            text: 'Profile',            private: true,        }    )` `    return(        <>            <nav ``className``='menu__Nav'>               
    ` `                    {routes.map((``route``, ``index``) => (                           
  •                             {                                ``route``.private && !auth.user ? (                                    <>                                                                    ) : (                                    <``NavLink``                                    // className={({ isActive }) => ''}                                        ``style``={({ ``isActive`` }) => ({                                             color: ``isActive`` ? 'blue' : 'purple'                                        })}                                        ``to``={``route``.to}                                    > {``route``.text} </``NavLink``>                                )                            }                       
  •                     ))}               
            </nav>            )}` `export { Menu }`
Este es el código para validar las si las rutas son públicas o privadas en la primera iteración (es código para TypeScript, muy similar a JS pero con tipado un poco más estricto): ```ts import React from 'react'; // import { Link, NavLink } from 'react-router-dom' import { NavLink } from 'react-router-dom' import { useAuth } from './../hooks/auth' const Menu: React.FC = () => { const auth:any = useAuth(); const routes = [] routes.push( { to: '/', text: 'Home', private: false, }, { to: '/blog', text: 'Blog', private: false, }, { to: '/login', text: 'Login', private: false, }, { to: '/logout', text: 'Logout', private: true, }, { to: '/profile', text: 'Profile', private: true, } ) return( <> <nav className='menu__Nav'>
    {routes.map((route, index) => (
  • { route.private && !auth.user ? ( <> ) : ( <NavLink // className={({ isActive }) => ''} style={({ isActive }) => ({ color: isActive ? 'blue' : 'purple' })} to={route.to} > {route.text} </NavLink> ) }
  • ))}
</nav> ) } export { Menu } ```
if((!rout.privete && auth.user ) && (rout.to === "/login")) return null
```js if((!rout.privete && auth.user ) && (rout.to === "/login")) return null ```  if((!rout.privete && auth.user ) && (rout.to === "/login")) return null

pensaba que con el return ya se finalazaba la ejecucion del codigo… pero se segun GPT el return null dentro del map afecta solo al elemento actual, no al resto de los elementos del array. por lo tanto luego del return; map continua con la ejecucion del codigo. esto aplica tanto para JSX como para javascript vanilla.

![](https://static.platzi.com/media/user_upload/image-b6688365-74f1-4faf-84cf-e8cc5fd625cc.jpg)
Yo puse: if (route.text === 'login' &&& auth.user) return null;
Reto 2 Para evitar que la app se totee proveer un nombre por default cuando el valor que recibimos es null ![](https://static.platzi.com/media/user_upload/image-3e3f345b-6370-4cfd-b207-4e1e85120e1d.jpg)
haciendo el truco a la inversa agregando una propiedad como publica en donde si la ruta es publica y esta autenticado desaparece  ```js if (route.public && !!auth.user) return null routes.push({ to: "/", text: "Home", private: false, public: false, }); ```
![](https://static.platzi.com/media/user_upload/code-471fdd7d-0631-46a4-a770-1620abcb2be2.jpg)
```js if ((route.private && !auth.user) || (route.to === '/login' && auth.user)) return null ```
Esta fue mi solución: ![](https://static.platzi.com/media/user_upload/image-38deec07-f378-44fe-9ff0-5de5c3dd339b.jpg)

8:39 me saco un susto con audífonos profe.

Solución utilizando un custom “middleware” el cual validara los datos antes de renderizar el contenido que le pasemos. Funciona como un componente padre que si todas las validaciones están bien renderiza al hijo y así protegemos todas las rutas que queramos validar sesión con 1 sola función.

Archivo protectedRoutes.jsx

import React from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../Components/auth";

const ProtectedRoutes = ({children}) =>{
    const navigate = useNavigate();
    const { user } = useAuth();
    React.useEffect(()=>{
        if (!user?.username) return navigate('/login')
    }, [])
    
    return children

}

export { ProtectedRoutes }

Archivo ProfilePage.jsx

import React from "react";
import { ProtectedRoutes } from "../middlewares/protectedRoutes";
import { useAuth } from "./auth";

const ProfilePage = () =>{
    const auth = useAuth();
    return (
        <>
            <ProtectedRoutes>
            <h1>Welcome!</h1>
            <p>{auth.user?.username}</p>
            </ProtectedRoutes>
        </>
    )
}

export { ProfilePage }

Mi solución fue añadir un condicional más

 if(route.text == "Login" && auth.user) return null
if ((route.publicOnly && auth.user) || (route.private && !auth.user))
            return null;

para @juandc, que es un crack explicando, pero siempre tiene dudas de que usan los objetos.
los objetos usan LLAVES.
los objetos contienen LLAVE y valor, y se separan con LLAVES {}