React Router es una librería que nos ayudará a crear las diferentes rutas que una aplicación realizada en ReactJS pueda necesitar. Para ello cuenta con diferentes opciones y una configuración bastante sencilla que iremos viendo a lo largo de este tutorial.
Eligiendo el tipo de Router: Web
De entre las diferentes soluciones que React Training, los creadores de React Router* han creado para usar: Web y Native(y otra llamada Core), en esta ocasión vamos a elegir Web ya que es una manera muy simple de ver el funcionamiento.
Las manos en la masa: Creando una aplicación básica con create-react-app
Para este ejemplo vamos a necesitar una aplicación escrita en ReactJS, aunque al ser un ejemplo tampoco usaremos algo muy grande. Tú mismo puedes crear una base para trabajar en este tutorial con create-react-app
, si aún no tienes instalado este CLI para React puedes hacerlo escribiendo en tu consola:
$ npm install -g create-react-app
Una vez lo tengas instalado, posicionado en el lugar donde queremos crear la aplicación correremos el comando espaciado del nombre de la aplicación, tal que así:
$ create-react-app ejemplo_router
Instalación de React Router
Ya dentro del proyecto, necesitaremos añadir la librería de React Router como una dependencia, para ello haremos otra instalación como la que acabamos de hacer:
$ npm install react-router-dom
La diferencia con la instalación anterior es que esta última dependencia no será global sino única del proyecto.
Inicialización de React Router
Siguiendo la estructura de create-react-app
, nuestro componente principal está localizado en /src/App.js
, luego, este es llamado por ReactDOM
lo cual nos interesa que siga ocurriendo, por lo que en App.js
vamos a inicializar React Router y a exportar la definición de las rutas, que será en este caso el entrypoint para ReactDOM.
Para ello, necesitamos importar alguna que otra parte de la librería:
import {
HashRouter as Router,
Route
} from 'react-router-dom'
También necesitaremos un componente que agrupe la definición de rutas, en mi caso lo he llamado myRouter
y me quedó tal que así:
class myRouter extends Component {
render() {
return(
<Router>
<div>
</div>
</Router>
)
}
}
export default myRouter;
Si te fijas, dentro del método render()
ya he colocado el componente Router
que va a llevar dentro todas las rutas. En el caso de que vayamos a colocar más de una ruta, en las últimas versiones de React Router, se nos piden que estas vayan agrupadas en un <div>
.
Router
, como habrás visto al exportarlo no es más que una parte de la librería en realidad llamada HashRouter
. En este caso, ocurre que hay más de una manera de gestionar las rutas y yo he elegido un sistema de Hashes, aunque vamos a ver todos los disponibles en el siguiente apartado.
Tipos de Router
-
<BrowserRouter>
: Al usar este tipo de router tus rutas serán gestionadas mediante el API de HTML5 history. -
<HashRouter>
: Este tipo de router usawindow.location.hash
, una información que provee el objeto Window de JavaScript y con el que va detectando las rutas(es uno de mis preferidos). -
<MemoryRouter>
: Este tipo de router no comprueba algo como la barra de direcciones si no que tiene las rutas en memoria y es útil en casos de uso como React Native. -
<Switch>
: Comprueba todas las rutas en orden y devuelve la que coincida.
Definiendo rutas
Una vez tenemos claro los tipos de router entre los que podemos elegir y tenemos preparado el componente que va a llevar las rutas, deberemos de definirlas. Si vuelves a comprobar el archivo, verás que también exportamos en su momento un componente Route
con el que haremos posible el uso de estas.
En nuestro caso, al ser un ejemplo muy básico sólo vamos a tener dos rutas:
- En la ruta principal(
/
) vamos a renderizar el componente que viene por defecto en ReactJS. - En una ruta de noticias(
/news
) vamos a renderizar algún texto estático.
Para hacer posible estas rutas deberemos de crear el componente de la última ruta mencionada, en nuestro caso para hacerlo aún más sencillo lo crearemos en el mismo archivo:
class News extends Component {
render() {
return(
<h1>Esta es la página de noticias. ¿A qué mola, eh?</h1>
)
}
}
Con todos los componentes listos llamaremos a Route
como cualquier componente de ReactJS por cada ruta que querramos crear, en nuestro caso deberemos de realizarlo dentro del div
del componente myRouter
:
class myRouter extends Component {
render() {
return(
<Router>
<div>
<Route path="/" component={App} />
<Route path="/news" component={News} />
</div>
</Router>
)
}
}
Apreciamos en la llamada a Route
los siguientes parámetros:
path
con el que mediante un texto le definiremos la ruta.component
el cual llevará el componente que vayamos a enseñar(si no está en el mismo archivo habrá que importarlo, claro).
Si pruebas la definición de rutas que acabamos de crear te darás cuenta que en el caso de
/news
se están renderizando ambos componentes y no es lo que queremos. El motivo por el que se están renderizando es que/news
tiene tanto/
como/news
y el sistema cree que debe mostrar ambos. Para evitar esto hay que colocarexact
dentro de<Route />
.
Rutas con parámetros
Hay casos en los que la ruta no va a ser un componente estático, si no que vamos a necesitar añadir parámetros a esta para en base a este solicitar a una API datos que rellenaremos en la vista. Un ejemplo de esto sería una página de "Mi Perfil" en una aplicación.
Para ello basta con añadir a el path
de la ruta la estructura típica de los parámetros. Por si no tienes constancia de ello se hace de la siguiente manera: /:nombre_parametro
. Siguiendo el ejemplo que te comentaba podría resultarte algo como: /usuarios/:id
.
Para acceder a este parámetro, en el componente podrás acceder a un objeto que contiene el resultado desde this.props.location
.
Componente <Link />
React Router viene preparado para trabajar tal y como una Single Page Application, la cual se caracteriza por no recargar el navegador al cambiar de página. Si queremos hacer esto posible, para cada enlace a otra ruta de la aplicación deberemos de usar el componente Link
.
Veamos un ejemplo:
import {
HashRouter as Router,
Route,
Link
} from 'react-router-dom'
[...]
class News extends Component {
render() {
return(
<div class="content">
<h1>Esta es la página de noticias. ¿A qué mola, eh?</h1>
<Link to="/">Volver a la página de inicio</Link>
</div>
)
}
}
Conclusiones
Como has podido comprobar, React Router es una librería muy sencilla y muy intuitiva que nos ayudará a resolver el problema de routing en React.
Con React Router podemos llegar a crear una aplicación bastante grande y tal y como lo hacen las demás SPA, lo cual es un punto a favor ya que es una teoría reciente para el desarrollo de aplicaciones.
Por si te has perdido en alguno de los puntos o quieres confirmar que lo hayas entendido todo te dejo el código completo del archivo que hemos estado trabajando:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {
HashRouter as Router,
Route
} from 'react-router-dom'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
class News extends Component {
render() {
return(
<h1>Esta es la página de noticias. ¿A qué mola, eh?</h1>
)
}
}
class myRouter extends Component {
render() {
return(
<Router>
<div>
<Route exact path="/" component={App} />
<Route path="/news" component={News} />
</div>
</Router>
)
}
}
export default myRouter;