¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Cuestiones adicionales y avanzadas
Notas del curso Desarrollo de aplicaciones web con React 18
A estas alturas ya conoces todos los conceptos de React que te permiten desarrollar prácticamente cualquier aplicación de Front-End de tipo SPA (Singe Page Application, aplicaciones de una sola página) con esta biblioteca. También has aprendido los conceptos relacionados con la reactividad, así como a implementarlos de manera más sencilla y profesional utilizando Redux. Sabes conectarte con una API para consultar datos y realizar acciones, así como hacer caché de esos datos y actualizarlos en tiempo real.
Sin embargo, React sigue siendo una biblioteca enfocada únicamente en crear componentes de UI reutilizables, por lo que carece de otras funcionalidades que son necesarias para desarrollar aplicaciones completas. En este módulo veremos cómo suplir algunas de estas limitaciones propias de React mediante otras bibliotecas y herramientas complementarias.
En concreto aprenderás a:
- Gestionar el enrutamiento de una aplicación React mediante React Router, de modo que puedas crear una aplicación de varias páginas sin perder la naturaleza de SPA.
- Gestión de sesiones de usuario, realizando autenticación y autorización de usuarios, de modo que puedas añadir seguridad en el lado cliente para tu aplicación, mostrando a cada uno lo que le corresponda.
Navegación por páginas mediante React Router
Las aplicaciones que desarrollamos con React suelen seguir un paradigma de una única página (o SPA, single page application). Esto puede presentar limitaciones cuando hay distintas partes de la aplicación que se deben mostrar en diferentes momentos. Una opción sería cargar la interfaz al completo de todas las posibles pantallas y mostrar u ocultar parte de ella con variables booleanas. Sin embargo, esto implica que el navegador potencialmente tendrá que descargar mucha más información de la que se va a usar, ralentizando la carga de la página web.
La solución a esta problemática consiste en utilizar un sistema de enrutamiento (routing) que preserve la naturaleza de SPA de nuestra aplicación React pero que al mismo tiempo nos siga proporcionando rutas únicas para cada parte de la aplicación. El más utilizado y completo viene en forma de librería y se denomina React Router. A lo largo de esta lección aprenderás a manejarla mediante un ejemplo sencillo, y a continuación lo integraremos en nuestra aplicación gestora de tareas.
La idea de esta lección es que vayas creando paso a paso un proyecto desde cero, siguiendo las indicaciones que se van dando en cada apartado, hasta llegar a construir la aplicación completa. Deberás hacerlo así si quieres conocer bien todos los detalles del funcionamiento, ya que es un tema bastante complejo.
Mapeo de rutas
Para comenzar, crea un nuevo proyecto de tipo React con Vite y añade las dependencias de React Router y LocalForage mediante el siguiente comando:
npm install react-router-dom localforage
LocalForage es una biblioteca que nos permite almacenar datos en el navegador de forma persistente y asíncrona, de forma que no se pierdan al recargar la página. Al contrario que usando tan solo localstorage, es capaz de almacenar otros tipos de datos que no sean cadenas de texto. Se utiliza en el archivo gallery.js para guardar alguna información sobre las fotos del ejemplo.
Además, puedes eliminar todos los archivos que se incluyen por defecto en el directorio src/ salvo main.jsx e index.css, que los mantendremos para modificarlos. Añade los siguientes imports al archivo main.jsx:
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from "react-router-dom"
Encontrarás en los archivos asociados a esta lección un index.css que puedes copiar directamente, ya que no incluye nada relevante a lo que nos ocupa, pero mejorará la estética de la aplicación 😉
El funcionamiento de React Router consiste en asociar diferentes elementos de React a rutas en nuestra aplicación. Cada ruta se distingue por un camino diferente desde la raíz (/).
Por ejemplo, como demostración de esta funcionalidad, vamos a construir una sencilla aplicación para mostrar una galería de fotografías donde los usuarios podrán votar por sus fotos favoritas. Las rutas que definiremos, por tanto, tendrán el siguiente esquema:
/: raíz de la aplicación, que mostrará el índice de fotos/photos/:id: página individual para cada fotografía/photos/:id/voted: página que se mostrará cuando se haya votado por una foto
Si traducimos la lista de caminos a un grafo, podría tener el siguiente aspecto. Se han añadido los nombres de los componentes que vamos a implementar en cada ruta y se observa mejor que unas rutas parten de otras previas:
Para definir cada una de estas rutas utilizaremos elementos de tipo <Route>. Las rutas recibirán como propiedades el camino que representan y el elemento que tienen que renderizar. La ventaja de enrutar de esta forma, en lugar de generar y enviar páginas completas, es que, en cada ruta, podemos definir únicamente las partes de la aplicación que deben cambiar. Para ello, simplemente anidaremos unas rutas dentro de otras y se renderizarán los elementos en el lugar apropiado que marcaremos más adelante.
Tal y como hemos definido el esquema de rutas previamente, escribimos tantos elementos <Route> como rutas incluidas en el índice (que se marcan con la propiedad index) como en el listado que veremos en breve.
Además, especificaremos el parámetro :imageId en la ruta photos/:imageId de forma que, al ir precedido de dos puntos, capturará todas las rutas que empiecen por photos/ y lo que siga se incluirá como parámetro.
Estas rutas las pasaremos por la función createRoutesFromElements() para que se conviertan en un parámetro apto para crear el objeto enrutador mediante createBrowserRouter():
const router = createBrowserRouter(createRoutesFromElements( <Route path="/" element={<Root />}> <Route index element={<Index />} /> <Route path="photos/:imageId" element={<Photo />}> <Route index element={<Vote />} /> <Route path="voted" element={<Voted />} /> </Route> </Route> ))
Los caminos de rutas anidadas se anidarán también: por ejemplo, si la ruta de camino voted está anidada bajo la de camino photos/:imageId, entonces llegaremos a la primera cuando la URL tenga el formato /photos/:imageId/voted.
El browser router que hemos instanciado es un enrutador que utiliza la URL del navegador para controlar el contenido de la página, pero también podríamos utilizar createMemoryRouter() si queremos que dicha URL no se modifique (o estamos desarrollando en un entorno en el que no existe tal URL, por ejemplo, una aplicación de escritorio), o createHashRouter() si fuera necesario prefijar una almohadilla # a la ruta en la URL, por ejemplo, cuando no permitamos en el servidor peticiones a rutas distintas de la raíz de la aplicación.
Para utilizar el router que acabamos de crear, sustituiremos el elemento <App> que se renderiza en la raíz de la aplicación por el <RouterProvider> asociado a nuestro objeto:
ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> )

