React — React Router

Mauricio Garcia
15 min readFeb 23, 2021

--

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ífica www.url.com/about, .../products, .../gallery, etc, así como las páginas generadas dinámicamente .../products/shirts/abc donde abc es el ID 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 llamada Home
  • Cuando la URL sea igual a /shirts/ deberá cargar el componente o página llamada Items
  • Cuando la URL sea igual a /shirts/10198 deberá cargar el componente o página llamada Item
  • Cuando la URL sea igual a /pay deberá cargar el componente o página llamada Payment
  • Cuando la URL sea igual a /about deberá cargar el componente o página llamada About

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 rutas URL normales (*.com/about), se requiere que el servidor esté configurado correctamente (en el caso de create-react-app ya viene predeterminado)[ref]
  • <HashRouter>: Almacena la ubicación en la parte de la URL 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> la URL 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 la URL 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 una URL 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 de URL suma uno.
  • action: La acción actual ( PUSH, REPLACE, POP), por default cuando cambiamos entre páginas es PUSH.
  • 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 historial
  • go(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 a go(-1)
  • goForward(): Función que va a la siguiente entrada de la pila del historia, equivale a go(+1)
  • location: La ubicación actual, donde tiene las siguientes propiedades:
  • pathname: La ruta de la URL (sin el dominio)
  • search: La cadena de consulta de URL
  • hash: El fragmento de hash de URL

— 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 la URL (sin el dominio)
  • search: La cadena de consulta de URL
  • hash: El fragmento de hash de URL

— 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 la URL 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 la URL
  • isExact:Regresa true si coincide la URL 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 la URL
  • isExact:Regresa true si coincide la URL 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 la URL, caso contrario nos regresa null

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 componente Redirect 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 componente Submenú.
  • 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 la URL 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]

--

--