React — React Router
Muchas de las funciones relacionadas con el manejo de rutas han sido simplificadas y mejoradas, lo que permite una experiencia de desarrollo más eficiente y fácil de mantener. Si deseas ver esta entrada pero con la versión 6, da click aquí.
Temario
- Introducción
- ¿Qué es enrutamiento?
- ¿Qué es React Router?
- Ejemplo: básico con React Router V5
- Componentes primarios de React Router
- Los hooks de React Router
- Parámetros desde la URL
- Enrutamiento anidado
- Redireccionamiento
- Ejemplo básico general
i. Introducción
Sabemos que React es una biblioteca para crear aplicaciones de una sola página (SPA).
SPA (Single Page Application): Es una aplicación de una sola página,que funciona en el navegador y que no requiere recarga de páginas extras, NO es necesario actualizar TODA la página, ya que el contenido se descarga automáticamente.
La librerías o Frameworks como React, Angular, Vue… son las encargadas de realizar el trabajo del lado del cliente para que funcione como una aplicación de una sola página.
La mayoría de los usuarios que navega en internet, está acostumbrada a los cambios entre páginas, por lo tanto, espera que todas las páginas funcionen de la siguiente manera:
- Cada una de las vistas de la aplicación debe tener una
URL
específicawww.url.com/about, .../products, .../gallery, etc
, así como las páginas generadas dinámicamente.../products/shirts/abc
dondeabc
es elID
de algún producto. - Los botones de adelante y atrás de los navegadores, deben funcionar como se espera.
- Si se ingresa directamente a una
URL
específica.../products/pants/abc
, realmente funcione.
De manera natural no podemos realizar estas acciones con React, por lo que se han creado APIS que ayudan a poder tener enrutamiento de páginas, pero… con todas las ventajas de una SPA.
Nota: Existen diferentes APIS para el manejo de páginas, pero para esta storie vamos a utilizar la más popular: React Router[ref], que es una API de terceros (no es oficial de React).
ii. ¿Qué es enrutamiento?
Es el proceso de mantener sincronizada la URL con el contenido de una aplicación, permitiéndonos controlar el flujo de datos de la aplicación.
Veamos un ejemplo gráfico:
Podemos observar que dependiendo la ruta es el contenido que se va a mostrar. A nivel código quedaría algo así:
Le estamos indicando:
- Cuando la
URL
sea igual a/
deberá cargar el componente o página llamadaHome
- Cuando la
URL
sea igual a/shirts/
deberá cargar el componente o página llamadaItems
- Cuando la
URL
sea igual a/shirts/10198
deberá cargar el componente o página llamadaItem
- Cuando la
URL
sea igual a/pay
deberá cargar el componente o página llamadaPayment
- Cuando la
URL
sea igual a/about
deberá cargar el componente o página llamadaAbout
iii. ¿Qué es React Router?
React Router es una librería de enrutamiento construida sobre React, donde, nos va a permitir crear enrutamiento dinámico de manera sencilla y simple.
:: Breve historia
- Por allá del 2014 Michael Jackson[ref] y Ryan Florence[ref] tuvieron la genial idea de crear un enrutador para React.
- Para acoplarlo a una aplicación es tan simple que la página de React lo recomienda[ref].
- A finales del 2019 deciden fusionarse con el enrutador reach[ref], con el objetivo de tener lo mejor de ambos, donde, a principios del 2020 sale la versión 5 (teniendo soporte para hooks).
- Actualmente están trabajando en la versión 6 [ref].
iv. Ejemplo básico con React Router V5
Vamos a crear un proyecto con create-react-app
:
Si tienes dudas por que npx o llegaste aquí directo, te recomiendo que inicies primero por acá (Mi primera App con create-react-app [ref])
:: Instalación
Vamos a la carpeta e instalamos React router:
:: Sintaxis básica
— En el import
— En el código
:: Ejemplo
Abrimos el archivo App.js
, y agregamos el siguiente código:
— Ejemplo completo
— Descarga el código
Github[tag: 0.1.0][ref].
v. Componentes primarios de React Router
React router se divide en 3 tipos:
- Enrutadores:
<Browserouter>, <HashRouter>
- Comparadores de ruta:
<Switch>, <Route>
- Navegadores:
<Link>, <NavLink>, <Redirect>
:: Enrutadores
Cada aplicación que necesite React router deberá tener un componente enrutador:
<BrowserRouter>
: Usa rutasURL
normales (*.com/about
), se requiere que el servidor esté configurado correctamente (en el caso decreate-react-app
ya viene predeterminado)[ref]<HashRouter>
: Almacena la ubicación en la parte de laURL
con un hash#
(*.com/#/about
), de esta forma no se necesita ninguna configuración especial del lado del servidor.
:: Comparadores de ruta
<Switch>
: Este componente se va a encargar de buscar a través de sus hijos<Route>
laURL
que sea igual o parecida para mostrar su contenido, en caso de que encuentre ignorará los demás; en caso de que no encuentre nada devolveránull
.<Route>
: Es el componente que va a tener laURL
que acepta, así como el contenido a mostrar.
Nota: Se recomienda poner primero las rutas más específicas a las menos específicas, ya que se corre el riesgo que haga mal el enrutamiento.
:: Navegadores
<Link>
: Componente para crear enlaces dentro de la aplicación.<NavLink>
: Es un componente especial, que nos sirve para poder cambiar el estilo del enlace (siempre y cuando coincida).<Redirect>
: Cuando se quiere forzar la navegación a unaURL
específica.
— Resumiendo
React Router tiene un componente llamado Switch
que se va a encargar de buscar en sus hijos Route
la URL
que coincida para mostrar su contenido:
:: Ejemplo
Imagina que tenemos una aplicación, donde tiene un menú <ul>
, el contenido dinámico y un footer <footer>
, la idea es que cada que se le de click a un ítem del menú solo cambie la parte interna, algo así:
Entonces, vamos a crear la carpeta src/Components
y dentro creamos los siguientes componentes:
src/Components/Home.jsx
src/Components/Gallery.jsx
src/Components/About.jsx
Ahora vamos a src/App.js
y configuramos nuestro enrutamiento e importamos los componentes creados:
En la animación de arriba podemos observar que solo renderiza una parte y no toda la página.
— Ejemplo completo
— Descarga el código
Github[tag: 0.2.0][ref].
vi. Los hooks de React Router
React router cuenta con hooks personalizados que nos van permitir acceder al estado del enrutador, los hooks con los que cuenta son:
:: useHistory
Este hook nos va a retornar un objeto mutable, donde nos va a a dar acceso a la historia de la instancia.
Se importa de la siguiente manera:
Se utiliza de la siguiente forma:
Y el objeto que retorna es el siguiente:
legth
: Número de entradas que tiene la pila del historial, por cada cambio deURL
suma uno.action
: La acción actual (PUSH, REPLACE, POP
), por default cuando cambiamos entre páginas esPUSH
.push(path, [state])
: Función que sirve para agregar una entrada a la pila del historial.replace(path, [state])
: Función que nos va a servir para reemplazar la entrada actual de la pila del historialgo(n)
: Función que nos va a servir para poder navegar por medio de la pila del historial, mediante un número.goBack()
: Función que va a la última entrada de la pila del historia, equivale ago(-1)
goForward()
: Función que va a la siguiente entrada de la pila del historia, equivale ago(+1)
location
: La ubicación actual, donde tiene las siguientes propiedades:- —
pathname
: La ruta de laURL
(sin el dominio) - —
search
: La cadena de consulta deURL
- —
hash
: El fragmento de hash deURL
— Es útil para:
- Cuando queremos acceder al historial de React Router (navegar, agregar, eliminar, modificar)
- Tiene como dependencia el paquete “history”[ref]
— Ejemplo
— Ejemplo Completo
— Descarga el código
Github[tag: 0.2.1][ref].
:: useLocation
Este hook nos va a retornar un objeto mutable, donde nos va a a dar acceso a la
URL
.
Se importa de la siguiente manera:
Se utiliza de la siguiente forma:
Y el objeto que retorna es el siguiente:
pathname
: La ruta de laURL
(sin el dominio)search
: La cadena de consulta deURL
hash
: El fragmento de hash deURL
— Es útil para:
- Saber en qué parte de la aplicación nos encontramos.
- Es parecido a
window.location
, pero representando el estado y ubicación del enrutador. - Para poder hacer el breadcrumb[ref].
- Así como la “huella” de la página (cuando usamos algún analizador web).
— Ejemplo
En el componente Home
agregamos el botón:
En el componente Gallery
, leemos el hook, useLocation
,vamos a ocupar URLSearchParams
[ref] para obtener los parámetros que se encuentran después del ?
:
Vamos a utilizar el parámetro enviado. La idea es saber cuantas imágenes debe renderizar, en caso de que no venga el parámetro por default deben ser 5:
— Ejemplo Completo
— Descarga el código
Github[tag: 0.2.2][ref].
:: useParams
Este hook nos va a retornar un objeto, donde nos va a retornar clave/valor de los parámetros de la
URL
.
Se importa de la siguiente manera:
Se utiliza de la siguiente forma:
— Es útil para:
- Obtener los valores dinámicos que se mandan por la
URL
. - Es muy común utilizarlo cuando queremos mostrar algún producto, una entrada de blog.
— Ejemplo
Nota: El manejo de rutas dinámicas, lo veremos en el siguiente tema a detalle, por ahora solo nos enfocaremos en el hook
useParams
.
Vamos a hacer el mismo ejemplo anterior, pero ahora usando useParams
:
En el componente App
, le indicamos al <Route>
de gallery
que va a recibir parámetros (en este caso se llamará print
)
En el componente Home
agregamos el botón:
En el componente Gallery
, leemos el hook useParams
. La idea es saber cuantas imágenes debe renderizar:
— Ejemplo Completo
— Descarga el código
Github[tag: 0.2.3][ref]
:: useRouteMatch
Este hook tiene dos funcionalidades: (1) Nos retorna un objeto para tener acceso la
URL
actual y a los parámetros. (2) Intenta coincidir laURL
actual como lo haría el componente<Router>
Se importa de la siguiente manera:
— (1)
Se utiliza de la siguiente forma:
Y el objeto que retorna es el siguiente:
params
: Va a retornar clave/valor de los parámetros de laURL
isExact
:Regresatrue
si coincide laURL
completa,false caso contrario
path
: La ruta con las variables dinámicos, es útil para construir<Route>
anidados.URL
: La ruta con los valores dinámicos, es útil para construir<Link>
anidados.
Ejemplo
Vamos a agregar la URL
actual en la galería:
Ejemplo completo
Descarga el código
Github[tag: 0.2.4][ref]
— (2)
Se utiliza de la siguiente forma:
Nota: También acepta un argumento, de tipo objeto[ref].
Y el objeto que retorna es el siguiente:
params
: Va a retornar clave/valor de los parámetros de laURL
isExact
:Regresatrue
si coincide laURL
completa,false caso contrario
path
: La ruta con las variables dinámicos, es útil para construir<Route>
anidados.URL
: La ruta con los valores dinámicos, es útil para construir<Link>
anidados.
Ejemplo:
Nota: El manejo de rutas dinámicas, lo veremos en el siguiente tema a detalle, por ahora solo nos enfocaremos en el hook
useRouteMatch
Necesitamos presentar de manera genérica /about
, así como también uno personalizado /about/mauricio
o /about/angelica
, sin usar el hook, tendríamos que usar el componente <switch>
y agregar las dos posibles rutas:
Pero con el hook, podemos manejarlo desde el interior de nuestro componente de la siguiente manera:
Donde:
- (A) — Vamos a indicarle que ruta queremos leer, en este caso es
/about/:name
- (B) — Si regresa el objeto
match
es por que cumple con laURL
, caso contrario nos regresanull
Ejemplo completo
Descarga el código
Github[tag: 0.2.5][ref]
— Es útil para:
- Para acceder a coincidencias de rutas sin usar el componente
Route
- Para hacer rutas anidadas.
vii. Parámetros desde la URL
Los parámetros de la URL
nos van ayudar a representar el mismo componente en función de su URL
dinámica.
:: Sintaxis
Los parámetros, son marcadores de posición en la URL
, donde debe comenzar SIEMPRE con dos puntos (:
), la convención es similar a otros marcos web como Rails y Express.
— Ejemplos
:: Ejemplo
Imagina que tenemos una tienda de ropa, donde vendemos a hombres y mujeres, la idea es la siguiente:
- Tener un link para hombres
/mens
y otro para mujeres/ladies
- Ambos van a cargar el componente
Clothes
, donde va a tener un título.
En el componente App
, creamos el enrutamiento (donde vamos a utilizar URLs
dinámicas usando :
)
Podemos observar que hemos agregado el componente Router
, y en su atributo path
agregamos /:type
, que nos va a servir como identificador dentro del componente Clothes
.
Creamos una carpeta con el nombre components
y dentro el componente Clothes
:
Utilizamos el hook useParams
, para obtener los valores dinámicos de la URL
.
Si levantamos el servidor, debemos ver lo siguiente:
— Ejemplo completo
— Descarga el código
Github[tag: 0.3.0][ref]
viii. Enrutamiento anidado
No olvidemos que las rutas son componentes de React, por lo que podemos representarlas en cualquier parte de la aplicación (no solo en la App
), y esto incluye elementos secundarios, entonces, el enrutamiento anidado nos va a ayudar a crear subrutas en cualquier parte de la aplicación.
Continuando con el ejemplo anterior, la idea es:
- Cuando le demos click a un tipo, nos debe mostrar el título de la sección (este ya lo tenemos)
- Mostrar una lista de opciones (Outerwear, T-shirts), donde al darle click a una de ellas nos va a mandar a dicha sección, donde nos va a mostrar unas imagenes.
Entonces, dentro del componente Clothes
, vamos a generar nuevas subrutas:
Utilizamos el hook useRouteMatch
, para obtener la URL
estática /ladies
o /mens
(para ocupar en el componente <Link>
) así como la URL
dinámica /:type
(para ocupar en el componente <Route>
)
— Ejemplo completo
— Descarga el código
Github[tag: 0.3.1][ref]
ix. Redireccionamiento
React Router, también tiene la posibilidad de redireccionar a una página. Tenemos dos opciones de hacerlo:
- De manera manual, por medio del componente
Redirect
- Manera genérica, por medio del componente
Route
Es muy común utilizarlo:
- Cuando no se encuentra una página y queremos redireccionarlo a una de error.
- Se tienen páginas protegidas y hasta que inicie sesión, el usuario podrá acceder.
:: Sintaxis (Redirect)
También soporta un objeto:
:: Sintaxis (Route)
:: Ejemplo 1 (Redirect)
Continuando con nuestro ejemplo, la idea es solo aceptar /Mens, /Ladies
cualquier otra diferente debe redireccionar a /error
, entonces:
Dentro de la carpeta Components
creamos el componente NotFound
El siguiente paso es agregarlo en el enrutamiento de la página, en este caso es el archivo App
:
Ahora, dentro del componente Clothes
, hacemos la validación, en caso de que no cumpla lo redireccionamos:
Nota: Hay otras formas y quizás mejores de hacer la validación :)
Por último agregamos un vínculo “erróneo” en la App
Expliquemos paso a paso:
- Cuando se le da click a “Other” que es la ruta
/Other
, React Router busca internamente qué componente debe cargar. - En este caso encuentra que es
Clothes
. - El componente
Clothes
verifica si cumple o no con la condición, al no cumplir, retorna el componenteRedirect
hacia/error
caso contrario, carga el componente.
Importante: React router NO guarda en el historial
/Other
(esto es bastante útil, cuando le dan atrás se va a la última página visitada válida).
— Ejemplo completo
— Descarga el código
Github[tag: 0.3.2][ref]
:: Ejemplo 2 (Route)
Otra forma de redireccionar a una página, de manera más genérica, es con el componente Route
. Imagina que queremos evitar que el usuario ponga cualquier URL
, en este caso las que sean más de tres /ladies/T-shirts/bad
.
En el componente Clothes
, agregamos el componente:
Y por último, en el mismo componente, agregamos una URL
errónea, entonces, el componente completo, queda de la siguiente forma:
— Ejemplo completo
— Descarga el código
Github[tag: 0.3.3][ref]
x. Ejemplo básico general
Imagina que tienes una aplicación de carros, donde vamos a tener:
- Una lista de marcas, que va a ser el menú principal.
- Cuando se le de click a una de ellas, nos va a mostrar una lista de modelos que tiene (será un sub-menú)
- Cuando se le da click a un modelo, nos va a mostrar un título y una breve descripción.
Algo así:
Nota: Las marcas de los carros, así como los modelos son constantes, pero la idea es consumir APIS por medio de
fetch o Axios
.
Entonces, comencemos…
Donde:
- Componente
Menu
— Va a ser el menú principal, donde va a tener 4 marcas principales. - Componente
Brand
— Va a mostrar la marca del carro que se ha seleccionado, así como el componenteSubmenú
. - Componente
Submenu
— Una lista de modelos de carro, dependiendo de la marca de carro, son los modelos de carros a mostrar - Componente
Model
— Va a mostrar el modelo de carro que se le ha dado click, y una breve descripción (en este caso será estática) - Componente
Alink
— Nos va a servir para el ruteo de la página, y también para saber cuál está seleccionado.
Teniendo en cuenta lo de arriba, comencemos con la aplicación…
Lo primero que vamos a hacer es ir a la carpeta donde tenemos los proyectos, y desde ahí ejecutamos el siguiente comando:
Vamos a la carpeta del proyecto, e instalamos:
- Para los estilos:
aphrodite
Puedes utilizar el que más te guste, revisa esta story para conocer más (React — Formas de diseñar componentes de React, desde estilos en línea hasta CSS in JS[ref])
Vamos a crear el enrutamiento en el componente App
:
Vamos crear el componente Menu
(no olvides crear la carpeta Components
) y mostrar la lista de marcas (en este caso vamos a crear una constante llamada BRANDS
)
El segundo paso es agregarle los estilos:
Agregamos el componente a App
:
Hasta aquí debemos de ver lo siguiente:
Ahora vamos a crear el componente Alink
, donde:
- Debe aceptar como propiedades :
label
— Texto que va a mostrar,to
— URL a la que debe ir,styles
— Estilos que va a cargar
- (A) — El hook
useRouteMatch
lo usamos para validar que sea la ruta exacta, en caso de que se cumpla, retorna el componente, caso contrario no renderiza nada. - (B) — Usamos el componente
Link
, para el ruteo. - (C) — En caso de que sea la ruta exacta, agregamos los estilos del link activo.
El siguiente paso es agregarlo al componente Menu
:
Si hemos hecho todo bien, debemos de ver lo siguiente:
En la animación podemos observar que cuando se le da click a una de las marcas, se queda seleccionada.
El siguiente paso será crear el componente Brands
, por ahora solo vamos a cargar la marca:
Lo que sigue es crear el componente SubMenu
,
Donde:
- (A) — Vamos a tener una constante, donde vienen todos los modelos de acuerdo a la marca.
- (B) — Estilos.
- (C) — Vamos a utilizar el hook
useParams
, para obtener el valor de la marca. - (D) — Vamos a utilizar el hook
useRouterMatch
, para obtener laURL
actual. - (E) — Utilizamos el componente
ALink
, donde le pasamos todos los atributos necesarios.
Y por último lo agregamos al componente Brand
En el mismo componente, vamos a agregar los estilos, así como el nuevo ruteo:
Si hemos hecho todo bien, debemos de ver lo siguiente:
Por último creamos el componente Model
:
Si hemos hecho todo bien, debemos de ver lo siguiente:
— Ejemplo completo
— Descarga el código
Github[branch: example-url-params][ref]
En la siguiente entrega vamos a ver React — Creando una app de Pokémon Trading Card Game con hooks (useState, useEffect y custom Hooks), estilos con react-jss, consumir servicios con Axios y el ruteo con React Router
La entrega pasada vimos React — Portales
Bibliografía y links que te puede interesar…
Iconos e imágenes…