React Router
Hoy vamos a ver un tema muy interesante React-Router, está librería para javascript, es muy útil para manejar rutas, que muy recurrentemente cuando trabajamos con aplicaciones que las necesitan, se vuelven muy difícil de mantener y manejar, sobre todo cuando agregamos o modificamos alguna ruta.
Además de que tiene la capacidad de trabajar en el servidor y el cliente, y por si fuera poco, aplicaciones híbridas móviles, también se puede utilizar.
Para eso, React creó una buena librería que trabaja de la misma forma que sus componentes, así que ya están acostumbrados a trabajar con componentes de React les será muy sencillo aprender, y si aún no trabajan con componentes de React no tienen de qué preocuparse, aprénderlos es muy rápido.
Primero veamos un poco de un problema común, trabajando con otros lenguajes del lado del servidor, como PHP, que es uno de los más utilizados y sencillos de aprender.
Para ello imaginemos una aplicación con está estructura:
- index.php
- index.css
- index.js
Normalmente cuando necesitamos agregar una ruta de acceso a un punto de la aplicación, de la manera más sencilla posible, agregamos un nuevo archivo con extensión, .php para agregar la ruta, por ejemplo imáginemos que queremos agregar la ruta /main, entonces creamos un archivo main.php
Así nuestra nueva estructura, quedaría:
- index.php
- index.css
- index.js
- main.php
Así agregamos una nueva ruta a la aplicación, de manera que cuando ingresemos a nuestro dominio y vayamos a la ruta /main el servidor encontrará el archivo, lo ejecutará, y lo enviará al cliente que realizó la solicitud, aunque esto puede ser efectivo, en aplicaciones muy grandes, no es demasiado mantenible, y para este problema, se suelen utilizar frameworks como Laravel, para manejar rutas de manera eficiente, y haciendo tu código completamente mantenible. Los cuales requieren un conocimiento más amplio del lenguaje, pero para efectos prácticos, no los vamos a explicar aquí.
Ahora váyamos con React, en este ejemplo vamos a usar una aplicación ya iniciada, usaremos:
- Node JS, (v 8.11)
- Express (v 4.16)
- React (v 16)
- React-Router (v 4.3)
- Babel (v 6.26)
Entonces procedemos a instalar los paquetes necesarios con
npm install --save express react react-dom react-router babel-cli react-router-dom
Vamos a utilizar Babel, un precompilador de código, porque para la sintaxis de componentes de React, (JSX), es una característica de la librería, y el cual sólo podemos utilizar con un preset de Babel, con el cual podemos utilizar la característica sin problema y además utilizaremos también las nuevas características de javascript para Node.
Entonces instalaremos los presets también:
npm install --save babel-preset-react babel-preset-env
babel-preset-react para React.babel-preset-env para las características de javascript.
Además de esto, debemos configurarlos, para Babel lo único que hay que hacer, es crea un archivo .babelrc en el directorio raíz, aquí es donde irá nuestra configuración. El formato que utiliza es JSON, y el archivo quedaría de la siguiente manera.
{
presets: ['env', 'react']
}
Ahora hacemos nuestro código de entrada para la aplicación
index.js
import http from 'http'
import express from 'express'
const app = express()
app.get('/', function(request, response){
response.send('hola mundo')
})
http.createServer( app ).listen( process.env.PORT || 3000 )
// En javascript nativo, es decir que lo siguiente que voy a explicar
// también se puede usar en el navegador,
// se utiliza || para comprobar resultados
// y funciona para casos en que queremos poner un valor por default en
// una variable, en el caso anterior, primero toma una variable
// de entorno que se llama PORT, y si no se encuentra definida
// ( valor undefined ò false ) entonces que tome el valor 3000
De esta forma podemos definir rutas usando Express, un módulo de NPM, muy liviano, y muy sencillo de usar. Para probar que funciona, ejecutamos el comando
babel-node index.js
Ahora, para agregar a React debemos renderizar una página en el servidor y enviarla como un string, de está forma.
// Importamos las librerías de React
import React from 'react'
import ReactDOM from 'react-dom/server'
import http from 'http'
import express from 'express'
const app = express()
// Creamos una pequeña aplicación
// con la sintaxis de JSX
const App = () => {
return(
<h1>Hola mundo</h1>
)
}
app.get('/', function(request, response){
// Creamos el template string de la aplicación
const html = ReactDOM.renderToString( <App/> )
// Se lo enviamos al servidor
// Usamos template string
response.send(`
<!doctype HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Example Aplicación</title>
</head>
<body>
<div id="root">${ html }</div>
</body>
</html>
`)
})
http.createServer( app ).listen( process.env.PORT || 3000 )
El problema viene cuando queremos agregar otra ruta, ahí debemos llamar nuevamente al método get o post de Express para agregarla, además de llamar nuevamente también al método renderToString de React para renderizar una parte de la aplicación en esa ruta. Y aquí es donde entra React Router. Veamos como se configura
Primero debemos definir nuestras rutas, y qué componentes se renderizaran en esa ruta, para ello haremos un archivo llamado routes.js en el que contendrá nuestras rutas.
// En cada archivo dónde hagamos
// la sintaxis especial de React (JSX)
// debemos importar la librería
import React from 'react'
// Hacemos los componentes
// también podríamos importarlos desde archivos externos
// pero para efectos prácticos los crearé aquí mismo
const Entry = () => {
return(
<div>
<h1>Entry</h1>
<div>Entrada de al aplicación</div>
</div>
)
}
const Main = () => {
return(
<div>
<h1>Main</h1>
<div>Main de la aplicación</div>
</div>
)
}
const Other = () => {
return(
<div>
<h1>Otra ruta</h1>
<div>Aquí no hay nada</div>
</div>
)
}
// Exportamos un Array de items
// que cada uno contendrá un path
// es decir la dirección que le llegará en la petición
// y el componente que renderizará en esa dirección
// y una clave opcional que refiere si el componente
// se renderizará sólo cuando la dirección sea totalmente exacta
// además agregaremos una clave nosotros para hacer una pequeña
// barra de navegación, y que nos diriga a cada ruta
// en este ejemplo sólo usaremos tres rutas a los sumo
export default [{
// Este equivaldría al punto de entrada de la aplicación
// cómo si fuera nuestro index
path: '/',
exact: true,
pathString: 'Inicio',
component: Entry
}, {
// Main de la aplicación
path: '/main',
pathString: 'Main',
component: Main
}, {
// Otra aplicación
path: '/other',
pathString: 'Otra Ruta',
component: Other
}]
Ahora hagamos algunas modificaciones a nuestro archivo index.js quedando de está forma:
// Importamos las librerías de React
import React from 'react'
import ReactDOM from 'react-dom/server'
import http from 'http'
import express from 'express'
// Importamos los componentes
// necesarios de React Router
import { StaticRouter } from 'react-router'
import { Route, Link } from 'react-router-dom'
// Importamos nuestras rutas
import routes from './routes'
const app = express()
// Modificamos la aplicación
// para que maneje nuestras rutas
const App = () => {
return(
<div>
{
// Vamos a hacer también una pequeña barra de navegación
}
<ul>
{
routes.map( (route, i) => {
return (
<li key={i}><Link to={route.path}>{ route.pathString }</Link></li>
)
})
}
</ul>
{
// Por cada ruta vamos a necesitar un componente que
// decidirá cuando se verá
routes.map((route, i) => {
return (
<Route path={route.path} component={route.component} key={i} exact={route.exact}/>
)
})
}
</div>
)
}
app.get('*', function(request, response){
// Creamos el template string de la aplicación
const { url } = request
// El contexto, refiere a si queremos pasar algún parámetro de
// la petición como un usuario o algun dato necesario para la aplicación
// es un parámetro obligatorio, al igual que location,
// que al pasarle la localización de la url de petición del servidor
// le estamos pasando exactamente la dirección después del nombre
// de nuestro dominio, por eso he cambiado / esto por * esto
// en Express, además de definir las rutas, literales, también
// puedes usar expresiones regulares. * significa todas las peticiones
// de tipo GET y el contexto sólo será un objeto vacío, no nos interesa
// pasarle nada
const context = {}
// Lo agregamos a la aplicación
const html = ReactDOM.renderToString(
<StaticRouter location={url} context={context}>
<App/>
</StaticRouter>
)
// Se lo enviamos al servidor
response.send(`
<!doctype HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Example Aplicación</title>
</head>
<body>
<div id="root">${ html }</div>
</body>
</html>
`)
})
http.createServer( app ).listen( process.env.PORT || 3000 )
De esta forma nuestra aplicación ya maneja rutas, y si queremos modificar algo, sólo debemos ir a nuestro archivo, routes.js y modificar la dirección, y si queremos modificar algo en el propio contenido de la ruta, debemos ir a nuestro componente, pero no solamente React Router puede hacer esto, veamos más.
Para ver la siguiente característica de la librería, imaginemos que queremos que nos pasen parámetros en nuestra ruta, bueno pues lo primero que podríamos pensar es, lo pasamos como una petición del tipo GET, codificada en la url, de está forma, `dominio.com?par1=data1&par2=data3`, pero para los estándares de hoy, y para una aplicación que necesite de rutas, simples, y fácilmente recordables, esto se torna en un embrollo, completamente, bueno pues tanto Express como React Router saben manejar muy bien esto, si quieren probar el ejemplo de Express pueden ir a este enlace, aquí nos limitaremos a hacer el ejemplo de React Router
Para continuar con el ejemplo, agregemos una ruta nueva, que llamaremos /data y agregaremos algo especial para que pase nuestro parámetro, y le quitamos el pathString para que no lo muestre en la barra de navegación.
{
path: '/data/:name',
component: Data
}
Ahora cada vez que entremos a algo así /data/miNombre nos enviará el parámetro a nuestro componente, y nosotros podremos usar de esta forma.
const Data = (props) => {
return(
<div>
<h1>Ruta Data</h1>
<div>Hola {props.match.params.name}</div>
</div>
)
}
De esta forma, a la hora de pasar parámetros en tu URL, no tendrás la complicación de que ésta es muy complicada y difícil. La potencia de React Router se nota, porque la aplicación misma, gestiona las rutas, y no se deben delegar hacia otra parte, que a veces resulta más complicado. Esto es sólo el inicio de lo que puede hacer la librería. Pero hasta entonces, les dejo un enlace a el proyecto en Github para que lo prueben. Además también pueden consultar la guía oficial de React Router en inglés, por supuesto.
Comentarios
Publicar un comentario