Lo que sigue es crear un Layout, esto solo es con propósito de estética para la app, no es obligatorio.
🚨 Nota: Cada vez que creamos una nueva carpeta, también crearemos un archivo index.ts para agrupar y exportar todas las funciones y componentes de otros archivos que están dentro de la misma carpeta, y que dichas funciones puedan ser importadas a traves de una sola referencia a esto se le conoce como archivo barril.
Creamos la carpeta src/components y dentro creamos el archivo Layout.tsx para agregar:
interfaceProps{children:JSX.Element|JSX.Element[]}exportconstLayout=({children}:Props)=>{return(<div><h1>Protected Routes with <br/><span>React Router</span></h1>{children}<divclassName="logo"><imgsrc="https://cdn.svgporn.com/logos/react-router.svg"alt="react-router"/></div></div>)}
Creamos la carpeta src/pages y dentro creamos dos archivos:
HomePage.tsx, que actuara como la pagina que queremos que sea privada, o sea que solo usuarios con alguna autenticación puedan visualizar dicha pagina, incluso si el usuario sabe la URL de la pagina, no debe de poder verla.
LoginPage.txs, que actuara como la pagina publica que cualquiera que no tenga autenticación pueda ver, pero si el usuario ya tiene una autenticación entonces esta pagina no debe ser visible ni conociendo la URL.
Después creamos una carpeta src/routes y creamos el archivo AppRouter.tsx.
Este archivo sera el root de nuestro router, de aquí se desencadenaran las demás rutas.
Creamos un componente funcional.
exportconstAppRouter=()=>{return()}
Tenemos que importar algunos componentes que nos ofrece react-router-dom.
BrowserRouter, este componente tiene que envolver toda nuestra aplicación ya que es un proveedor. Una opción también es colocarlo en el archivo src/main.tsx, pero en mi caso me gustaría ponerlo en este archivo AppRouter.tsx y como este es el root de las rutas entonces esto es lo que vamos a importar en src/App.tsx
Routes, este componente debe estar dentro del BrowserRouter, y es el contenedor de las rutas que maneja nuestra aplicación, y cada vez que la ubicación cambia, este componente busca entre todas sus rutas hijas, para encontrar una ruta que coincida con la ubicación y poder renderizar el elemento que expone esa ruta hija.
Route, este componente es donde se definirá la ruta (mediante la prop path) y el elemento a renderizar (mediante la prop element pasando un elemento JSX).
Cuando colocamos un '*' en la prop path, significa que en caso de que ninguna ruta anterior conicidad con la ubicación, entonces podemos renderizar una pagina 404, pero en este caso, se manda al usuario a otra ubicación.
Navigate, este componente sirve para cambiar la ubicación actual cuando se renderiza.
to, es la prop para colocar el path hacia donde quieres ir en tu aplicación.
replace es la prop para quitar del historial de navegación la actual ruta, y colocar la nueva ruta a la que te diriges. O sea que cuando quieras volver atrás, esa ya no estará la anterior pagina.
Notaras que va a renderizar el HomePage.tsx, esto es porque cuando entramos a nuestra app, por defecto el path / y coincide con la ruta que renderiza el HomePage.tsx
Y si en la barra de dirección colocas /login, entonces te muestra el LoginPage.tsx.
Pero si colocas otra cosa que no sea un simple / o /login, entonces por defecto seria * y renderiza el componente Navigate que te manda al /login.
🔒 Agregando protección de rutas.
Por defecto, puedes visualizar el HomePage.tsx pero no debería ser posible, ya que no tienes una "autenticación". Asi que vamos a convertir esta ruta en una ruta privada.
Vamos a crear un nuevo archivo en src/routes nombrado PrivateRoutes.tsx
Y dentro vamos a crear una nuevo conjunto de rutas, que serán nuestras rutas privadas.
Para anidar rutas necesitamos tanto el contenedor de rutas que es el componente Routes y las rutas como tal que son el componente Route
Aquí irán todas las rutas que queremos que sean privadas. Solamente movemos la ruta que renderiza el HomePage a este componente.
Y ademas agregaremos una nueva ruta para mandar al usuario en caso de que el usuario ingrese una ruta que no exista en .nuestra app.
Y ahora necesitamos hacer cambios en el AppRouter.tsx
Vamos a simular la autenticación con una simple variable (aunque en una app real lo mas probable es que venga de un API), lo importante es que tengas acceso a algún valor que te indique si el usuario esta autenticado o no y puedas usar dicho valor en el AppRouter.tsx:
Y ahora haremos una condición dentro del contenedor de Rutas, donde si el usuario esta autenticado entonces déjalo ver las rutas privadas y no muestres el login que en este punto sera innecesario ya que el usuario ya esta autenticado.
De lo contrario, no renderize el componente de rutas privadas y muestra el LoginPage
Y al final, después de la condición, seguimos manteniendo la ruta con el comodín [*] ya que si el usuario ingresa una ruta que no exista entonces, hay que mandarlo a alguna parte que si existe de nuestra app.
Nota que en la ruta donde usamos [] el path de la prop **to* es /login y no es simplemente login. Ya que si colocamos solo la palabra login entonces mantendrá la URL como esta y solo le adicionara /login, lo cual no queremos.
Por ejemplo, si estamos en http://localhost:5173/about y queremos mandar al usuario a login, y en el componente Navigate en la prop to solo colocamos login sin el / al inicio entonces la URL resultante seria http://localhost:5173/about/login pero nosotros queremos apuntar al root de nuestras rutas y es por eso que debemos colocar el símbolo / al inicio, para que te envié a la URL http://localhost:5173/login
También nota que el path de las rutas privadas es '/*' significa que cualquier ruta que coincida con el / entonces entra al componente PrivateRoutes.
Un ejemplo seria: tienes la ruta about/* y alguien coloca el en buscador about/me entonces eso seria permitido y accedería al elemento que renderiza esa ruta. Si quitaras el comodín [*] entonces la ruta about/me ya NO sera permitido.
Hasta aquí ya tendríamos nuestras rutas privadas, y una sola ruta "publica" pero que tal si tenemos mas rutas publicas como la de crear usuario, entonces debemos crear un nuevo componente llamado PublicRoutes.tsx
Y agregar las rutas que queremos que sean "publicas" o sea disponibles cuando el usuario no este autenticado.
Notaras que ambas rutas tienen el mismo path, pero no sera un problema ya que su existencia es condicional, o solo existirá una ruta siempre.
Por cierto, si necesitas que alguna ruta sea accedida con o sin autenticación entonces colócala en el AppRouter.tsx después de la condición.
Y asi tendríamos rutas tanto publicas y privadas. 🥳
🔒 Conclusión.
Las rutas privadas son de mucha relevancia hoy en dia en las aplicaciones. Y con ayuda de React Router Dom nos hace mucho mas fácil la implementación de dicho proceso.
Otra idea que te puedo dar es que en las rutas privadas puedes anidar otras rutas para dividirlos por rol por ejemplo, si un usuario tiene el rol de 'user' no podrá ver la pagina de Admin, pero si tiene el rol de 'admin' entonces si podrá ver dicha pagina.
Espero que te haya gustado esta publicación y que te haya ayudada a entender más sobre como usar React Router Dom para implementar la protección de rutas. 🤗
Esta forma de hacer rutas privadas, no es la única, si es que conoces alguna otra forma distinta o mejor de realizar esta funcionalidad con gusto puedes comentarla 🙌.
Te invito a que revises mi portafolio en caso de que estés interesado en contactarme para algún proyecto! Franklin Martinez Lucas
🔵 No olvides seguirme también en twitter: @Frankomtz361
Franklin Martinez
@frankomtz361
Hola a todos! 👋
Mi nombre es Franklin Martinez.
Soy desarrollador Front-End y me especializo en las tecnologías de JavaScript y React JS. ⚛️ También me gusta publicar ✍ algunos artículos.