Enrutamiento - React Router
Last updated
Was this helpful?
Last updated
Was this helpful?
En esta sesión veremos cómo usar React para escribir aplicaciones web de una sola página (Single Page Applications, en inglés) usando un complemento llamado .
Una de las características fundamentales de la Web es el enlace, link o URL (siglas en inglés de "localizador de recursos uniforme"). Los enlaces permiten relacionar páginas entre sí, que unas nos lleven a otras, pero quizá una de las cosas más importantes es que se pueden compartir para que otras personas accedan al mismo contenido que nosotros.
Cuando se habla de SPAs se hace referencia a un tipo de web que consta exclusivamente de una página: un solo archivo HTML, con archivos CSS y JavaScript. Toda la interacción transcurre dentro de esa página, manejada con JavaScript, que imita a una ventana de las aplicaciones de escritorio. Por eso muchas veces hablamos de aplicaciones web cuando nos referimos a SPAs. Sin embargo, en esta transformación de web a aplicación web se perdería la esencia más útil de la Web si no se conservase un sistema de enlaces que diferencie las diferentes páginas que componen la aplicación.
Para reconciliar esta situación aparecieron técnicas de routing en JavaScript (en el lado del cliente) que manipulan intensivamente los hashes (#
) de las URL y respetan la . Es decir, "simulan" distintas direcciones URL en el navegador, lo que se llaman rutas, de forma que el usuario puede usar los botones de "página anterior" y "página siguiente" del navegador para desplazarse por distintas pantallas de la aplicación web, y permiten compartir enlaces que lleven específicamente a una pantalla, aunque en realidad todo esté hecho en una sola página (SPA).
React Router es una librería compatible con React (aunque no desarrollada por el equipo de React) que nos permite especificar rutas en nuestra aplicación web usando componentes de React. Es decir, con otras librerías especificaríamos las rutas por código JavaScript, pero con React Router las escribiremos en componentes de React como <Route path='/about'>
.
React Router se aprovecha de la separación de la interfaz en componentes que hace React. La lógica básica de cómo funciona es simple: depende de la ruta de la página en la que estemos, se pinta un componente u otro. Por ejemplo, podríamos decirle que si estamos en la ruta /
renderice el componente <Home />
en la página, pero si estamos en la ruta /about
, que renderice el componente <About />
.
Una de las características de las SPAs es que también mantienen el estado entre pantallas de nuestra página. Con React Router y la arquitectura de componentes con estado que vimos en la sesión 3.10 esto se puede observar en el estado de nuestro componente principal, que normalmente se llamará algo parecido a <App />
. <App />
tiene el estado relativo a todos los componentes incluídos dentro de sí, y aunque cambiemos un componente dentro de él dependiendo de la ruta, seguimos conservando los datos del estado que tenemos en <App />
.
Para empezar a usar React Router, en nuestro proyecto generado con create-react-app
debemos instalar y guardar la dependencia de npm
de la siguiente manera:
Para activar el enrutado en nuestra aplicación, haremos lo siguiente. En nuestro archivo index.js
importaremos el componente HashRouter
, y renderizaremos nuestro componente principal <App />
dentro, como children
:
index.js:
En nuestro componente App.js
ahora ya podemos declarar las rutas. Importaremos Route
y Switch
. El componente Switch
incluirá dentro tantos componentes Route
como rutas queramos en nuestra web y se asegurará de que solo se pinte uno. Dentro de cada componente Switch
el contenido variará dependiendo de la ruta de la aplicación. A cada componente Route
le pasaremos por props
la clase del componente que queremos que se renderize:
App.js:
Una vez declaradas las rutas, ya podemos hacer enlaces a las distintas pantallas de nuestra aplicación web. Para esto usaremos el componente Link
, también de React Router, que se encargará de convertir nuestras rutas en enlaces. Le pasaremos una prop
de nombre to
con nuestra ruta:
Me gustan tus pestañas
Vamos a crear una web con 3 pestañas: 'home', 'pricing' y 'about'. Para eso, lo primero vamos a crear un nuevo proyecto con create-react-app
.
Ahora, creamos 3 componentes, uno por cada pestaña con un contenido lorem y con el nombre de la pestaña.
Luego, en nuestro componente principal (App
) vamos a dibujar las 3 pestañas (3 enlaces) con el nombre de cada una y ocupando el 100% del ancho de la ventana.
Finalmente instalamos React Router en nuestro proyecto, y conseguimos que al pinchar en una pestaña, se pinte debajo el componente correspondiente. ¡A por ello!
React router también nos facilita crear rutas que tengan parámetros, es decir, que no sean rutas fijas sino que dependen del algún valor. Por ejemplo, si tenemos un listado de elementos y queremos crear una ruta para cada uno de ellos.
En este ejemplo, vamos a crear rutas para varios del estilo /child/:id
donde :id
es un identificador único de cada elemento. En el elemento Switch
crearemos una nueva ruta Route
con ese path='/child/:id'
y que renderiza el componente Child
. Ahora, los enlaces de la cabecera enlazan a /child/1
, /child/2
, etc. Al hacer clic en alguno de estos enlaces, se renderiza el componente Child
al que le llegará por props
un parámetro match
que tiene información sobre los parámetros de la URL, en este caso, el número al final de la URL.
App.js:
Child.js:
Los componentes Route
aceptan distintas props
. En las secciones anteriores hemos visto la más básica, component
. Cuando pasamos la prop
así, el componente Route
renderiza este componente cuando la ruta coincida con la que especifica en path
. Sin embargo, podemos querer renderizar algo más complejo, o puede que queramos pasar props
a ese componente. Para esas situaciones, Route
acepta una prop
de nombre render
al que le pasaremos una función que devuelva lo que queremos que se pinte.
NOTA: al usar la función
render
la información del match no le llega directamente al componente que queremos pintar. Para que le llegue, debemos recogerla de lasprops
y pasársela como en el ejemplo anterior.
Directorio con detalle
PISTA: Para resolver este segundo ejercicio
PersonDetail
debe tener acceso al id de cada usuario y a los datos (que seguramente estarán en App). Usaremosrender
para poder pasarle ambos datos, recordando que los datos delmatch
debemos pasarlos explícitamente al contrario que usandocomponent
.
También podemos utilizar una tercera prop
de nombre children
disponible en Route
. Será también una función que devuelve lo que queremos que se pinte, pero se pintará siempre, tanto si estamos en la ruta como si no. La gracia de esto es que la función acepta un objeto como parámetro que nos pasará el componente Route
automáticamente y que incluye información sobre la ruta actual, con la que podremos modificar la salida. Por ejemplo, con la siguiente función podemos hacer fácilmente la lista de navegación de la página y que se destaque la ruta en la que estamos actualmente.
En este ejemplo vemos que se usa Route
de 2 formas: con children
para pintar el enlace con un estilo especial, y luego con render
para pintar el contenido.
Tutorial sencillo de React Router v4. Incluye más información sobre las distintas plataformas en las que React Router funciona y las diferencias con las versiones anteriores (en inglés).
Explicación en profundidad de cómo funciona un router del lado del cliente con JavaScript (en inglés).
Documentación oficial de React Router. Define la API y muestra ejemplos (en inglés).
Un ejemplo de como hacer esto lo tenemos en . Mirad cómo pasamos el emoji del chaval y cómo recogemos el ID de la ruta /child/:id
.
Vamos a partir del ejercicio de la sesión anterior sobre un directorio de personas. En la página principal aparecía un listado de personas con información de . Ahora vamos a hacer un enlace por cada persona de la lista para acceder a una vista de detalle de esa persona. Implementaremos la vista de detalle con un nuevo componente PersonDetail
al que navegaremos usando React router con una ruta por cada persona de la lista. ¡A por ello!