No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Navigate y redirects: protegiendo rutas privadas

13/30
Recursos

Aportes 9

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Navigate y redirects: protegiendo rutas privadas

Como mencionamos anteriormente, si un usuario intenta acceder a una ruta privada por medio del historial o la barra de búsqueda aún si esta no esta renderizada o no puede acceder lo que va a causar es que nuestra aplicación este en blanco, colapse y ya no se pueda interactuar hasta que recarguemos.

Para solucionar esto lo que haremos es protegerlas de verdad haciendo que si intentan acceder a una ruta parvada haga un redirect al home, a login o a profile dependiendo de la ruta donde intente acceder.

Para esto vamos primero a nuestro Profile.js:

// Importamos el componente navigate
import { useAuth } from '../../auth/auth';

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

  /* Preguntamos si hay un usuario registrado, si no, redirigimos 
	a la persona */ 
  if (!auth.user) {
    /* Con este componente podemos hacer el redirect hacia donde la 
		lógica de nuestra aplicación lo requiera */ 
    return <Navigate to="/login" />
  }

  return (
    <>
      <h1>Perfil</h1>
      <h1>Welcome {auth.user.username}</h1>
    </>
  );
}

De esta manera si no nos hemos registrado e intentamos acceder a Profile por medio de la barra de búsqueda nos redirigirá a nuestro login.

En caso de que necesitemos redireccionar varias veces a distintos sitios de nuestra aplicación veremos que hacer esto puede ser un poco repetitivo, debemos solucionar esto.

Vamos a auth.js y creemos una función que nos permita hacer esto más sencillo.

import { Navigate } from 'react-router-dom';

...
/* En este compoinente podemos hacer la validación que es la misma 
que utilizamos con anterioridad */
function AuthRoute(props) {
  const auth = useAuth();

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

  return props.children
}

export {
	...
  AuthRoute,
}

Luego simplemente implementamos este componente en el ProfilePage.js:

import { AuthRoute, useAuth } from '../../auth/auth';

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

  return (
    <AuthRoute>
      <h1>Perfil</h1>
      <h1>Welcome {auth.user.username}</h1>
    </AuthRoute>
  );
}

export { ProfilePage }

Si lo ejecutamos tendremos un error debido a que al renderizar el componente aún así lo redireccionemos como auth.user.username no existe y esto nos dará un error ya que en el componente lo estamos solicitando y esto nos genera un erro bloqueante al redireccionar a login.

Pero para que funcione esto en nuestro llamado desde App.js debemos importar a este componente ProfilePage dentro de un componente AuthRoute:

import { AuthProvider, useAuth, AuthRoute } from './Components/auth/auth'
...

function App() {
  return (
    <>
      <HashRouter>
        <AuthProvider>
          <Routes>
            ...
            <Route path='/profile' 
              element={
                <AuthRoute>
                  <ProfilePage /> {/* <-- */}
                </AuthRoute>
              } 
            />
          </Routes>
        </AuthProvider>

      </HashRouter>
    </>
  )
}

Y nuestro componente ProfilePage.js lo podemos dejar como estaba:

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

  return (
    <>
      <h1>Perfil</h1>
      <h1>Welcome {auth.user.username}</h1>
    </>
  );
}

Ahora haremos lo mismo con el Logout en App.js:

<Route path='/logout' 
  element={
    <AuthRoute>
      <LogoutPage />
    </AuthRoute>
  } 
/>

Lo único que nos queda por hacer es que cuando estemos autenticados no podamos acceder a la página de Login, porque estamos protegiendo las rutas privadas de un usuario público pero no la ruta pública de registro a un usuario privado. ¡Hagamos esto!

LoginPage.js

function LoginPage() {
	...	

  /* Como en este caso solo necesiamos hacer una validación lo 
  haremos directo en el componente preguntando si el usuario ya esta 
  registrado, si lo está lo redirigiremos a la página de Profile 
  usando el Navigate */
  if(auth.user) {
    return <Navigate to="/profile" />
  }

  return (
		...
	)
}

Y hemos terminado de proteger nuestras rutas y tener una mejor lógica de aplicación.

Navigate y redirects: protegiendo rutas privadas

Es muy importante poder proteger rutas que a las que no queremos que el usuario sin autenticar tenga acceso.

Una forma para solucionar esto seria la utilización del componente “Navigate” (Con N mayúscula), por medio de un if, donde evaluamos si el usuario está autenticado o no, vamos a indicarle a nuestro navegador que queremos redireccionar al usuario hacia “/login”

const auth = useAuth()

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

Esto ya es una solución, pero existe otra forma más simple de trabajar:

Dentro de nuestro archivo auth vamos a crear un componente, se podría llamar “AutenticadorDeRutas” o “AuthRoute”, y dentro de este vamos a incluir la lógica que aprendimos agregando que, en el caso de que si se pueda ver el contenido, se retorne el “props.children”

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

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

  return props.children
}

Por ultimo, tengo que decir que el componente AuthRouter es mejor llamarlo, justamente, en nuestro Router. De esta manera nos ahorramos problemas con valores que, asumimos, ya deberían existir en nuestros componentes si son renderizados.

<Route path='/profile' 
	element={
	  <AuthRoute>
	   <ProfilePage/>
	  </AuthRoute>
}/>

()= parentesis
{}=corchetes
[]=llaves

‘por favor vete’ jajajajaj

Es la segunda vez que veo la clase en semanas diferentes y todavia me sorprendo de lo buena que es !!!

Felicitaciones!!

Que bueno, este error me toco en algunas paginas, ahora no recuerdo bien cuales, pero al estar logeado tenia la opcion de login

Nuestra principal estrategia en este caso fue el usar validaciones para permitir o no que una persona pueda acceder a diferentes paginas dependiendo de si está logeada o no

No funciona porque a pesar de que si hace el redireccionamiento hacia login, igual sigue leyendo el resto del codigo del componente y cuando un usuario no se ha logeado, ese auth.user es null y en la linea 10 está intentando leer una propiedad que es nula

incluso una render function me parecería mas limpia para este caso