De Backend a Frontend con ReactJS
juan Vázquez Murga Colaboraciones 20/04/2017
A estas alturas presentarte ReactJS y hablarte de su historia, puede ser un poco de relleno, así que prefiero usar este artículo para que conozcas un poco como se trabaja en React. De todas formas, si aún no lo conoces te invito a que sigas este enlace: ReactJS.
ReactJS sigue la filosofía que Facebook aplica a sus interfaces y se basa en el paradigma de componentes. ¿Qué es un componente? Me alegra que me hagas esa pregunta. Un componente es una unidad autosuficiente, desacoplada y reutilizable, es decir, un cubo de Lego. Imagínate cómo Lego sirve sus cubos de diferentes colores y nos añade unas instrucciones para crear diferentes figuras usando siempre las mismas piezas básicas. Pues ahora, imagínate que puedes construir interfaces o software en general usando la misma filosofía, eso es un componente. No me quiero extender más en definiciones, aunque se podría ser más riguroso, para ello te dejo otro enlace para que te familiarices un poco más con este paradigma: CBSE.
La mejor forma de conocer React es viendo un ejemplo y, a ser posible, lo mas completo posible. Para ello, he seleccionado una funcionalidad muy básica pero a la que voy a aplicar los diferentes aspectos que debes tener en cuenta para desarrollar con React.
Funcionalidad: Listado de usuarios.
Características:
- Se listarán en una tabla.
- Se pueden ordenar por columnas.
¡Manos a la obra! Lo primero que tienes que hacer cuando trabajas con React es separar esta funcionalidad en componentes. Para ello, mi forma de pensar es la siguiente:
- Cada usuario será una fila de la tabla. Componente: User.
- El body de nuestra tabla será el listado de usuarios. Componente: Users.
- La tabla tendrá una cabecera interactiva para ordenar los usuarios. Componente: TableHeader.
- El resultado final será una tabla con la lista de usuarios. Componente: UsersTable.
Como puedes comprobar, los componentes de menor a mayor en términos de simplicidad y autonomía. Esto se debe a que la relación entre componentes se suele parecer a Matryoshkas. Puede parecer un poco naïve la forma de identificar los componentes, pero en mi experiencia, mejor así que olvidarme algún detalle por el camino y tener que rehacer componentes después.
Vamos a empezar a definir el primer componente:
Partes básicas de este componente son: render() y propTypes. Render() es el método principal que va a devolver la pieza de HTML para la que está pensado tu componente. Por otro lado, la declaración de propiedades de tu componente: User.PropTypes. Aquí definimos los parámetros de entrada que necesita tu componente.
Ya hemos definido nuestro componente User, ahora vamos por la lista de estos: .
Como vemos en este caso, necesitamos importar la definición del componente User, ya que, vamos a utilizarlo para cada uno de los usuarios. Por esta razón, empezamos describiendo los componentes de más simples a más complejos, necesitamos crecer en complejidad cuando creamos nuestros componentes para minimizar el riesgo de perdernos en los detalles de éstos.
Otro aspecto importante es el parámetro 'key'. Cuando llamamos al componente User en el loop donde vamos creando la lista de usuarios. Este atributo nos sirve para identificar de forma única cada instancia de un componente cuando creamos una lista de elementos. Si no usáramos este parámetro al crear nuestra lista, nos aparecería un aviso y no se mostrarían los usuarios.
Los siguientes dos componentes son sencillos, no voy a entretenerme en describirlos porque lo interesante viene después.
Una vez que tenemos descritos nuestros componentes y la relación entre ellos, pasamos a añadir sus interacciones. Nuestra interacción va a ser la ordenación por columnas del listado de usuarios. Esta funcionalidad se origina en el componente TableHeader y afectará a nuestro componente Users. Para ello, recurrimos al componente que los instancia a ambos: UsersTable. Estos componentes nos quedarían de la siguiente forma:
Ahora una nueva propiedad afecta a nuestros componentes TableHeader y Users. Users recibirá dos parámetros extras que indican cómo se tienen que ordernarlos usuarios (columna) y TableHeader recibirá la referencia a un método de UsersTable que permite variar los parámetros de ordenación de Users de forma interactiva.
En esta modificación, verás que han entrado en juego otra parte importante de un componente en React: States. Los states o estados, son variables que van a definir cómo se va a comportar nuestro componente. Son interactivas, lo cual permiten cambiar el comportamiento del componente en tiempo real y adaptarse a la acciones de los usuarios sobre la interfaz.
En nuestro ejemplo, en los componentes TableUsers y Uses en el constructor hemos definido unos estados para indicar como debe nuestro componente ordenar a los usuarios que, inicialmente, será por el apellido o lname (abreviado de last name). Luego, hemos añadido un comportamiento sobre los elementos de la cabezera de la tabla que al registrar un click va a llamar al método orderBy() del componente TableUsers que, modificará el valor del estado 'orderByColum' y que a su vez redefinirá el estado 'sortBy' de Users, que es el que finalmente determina el parámetro por el que ordenamos la lista de usuarios.
Sólo nos falta añadir un archivo extra donde indicaremos cómo renderizar nuestros componentes en nuestro HTML. Para ello, crearemos un archivo 'index.jsx' (yo lo he llamado asi, pero eres libre de llamarlo como quieras) con el siguiente contenido:
Pues ya está, ya tenemos todo listo para renderizar nuestro componente en un documento HTML y servirlo...casi, pero no :). Este código ha de ser compilado a código JS. Para ello, necesitamos hacer uso de Webpack con el que compilaremos nuestros componentes y generaremos un archivo final .js que será el que incluiremos en nuestro HTML.
Para el siguiente paso, necesitaremos tener nodeJS instalado en nuestro sistema y el gestor de paquetes npm. Vamos a ver los pasos a seguir sin entrar mucho en detalle. Para profundizar más, puedes buscar la definición de cada paquete y enterarte mejor para qué sirve y las posibilidades que ofrece.
Generamos nuestro package.json e inicializamos el projecto.
npm init
Tras esto, tendremos un archivo package.json en nuestra raíz del proyecto. Instalamos webpack:
npm i webpack
Instalamos algunas dependencias:
npm i babel-core babel-loader babel-preset-es2015 babel-preset-react extract-text-webpack-plugin
Y obviamente react:
npm i react react-dom
Una vez tenemos instalados los paquetes que vamos a utilizar, pasamos a crear el archivo de configuracion de webpack:
// ./webapack.config.js
var webpack = require('webpack'),
path = require('path')
ExtractTextPlugin = require('extract-text-webpack-plugin');
var JAVASCRIPT_DIR = path.resolve(__dirname, 'javascripts');
module.exports = {
entry: JAVASCRIPT_DIR + '/components/index.jsx',
output: {
path: JAVASCRIPT_DIR,
filename: 'application.js'
},
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
}
};
Con esta configuración, ya podemos ejecutar la siguiente orden:
webpack
Y veremos que nos ha generado en la carpeta js/ un archivo llamado 'application.js' con el código compilado de nuestros componentes. Ahora sí estamos listos para incluirlo en nuestro archivo HTML y ver el resultado.
Como bonus extra y, para mí es muy importante, debemos testear nuestros componentes. Para ello, tenemos una fantástica librería creada por AirBnB llamada Enzime, que junto con Mocha y Chai nos permiten generar una suite de test unitarios y de integración que nos van a asegurar la solidez de nuestra interfaz. Vamos a ver al menos cómo testearíamos el componente Users y si quieres más información acerca de testing en React te sugiero que vayas al repositiorio del proyecto Enzime.
Primero instalaremos los modulos que necesitamos:
npm i chai chai-enzyme enzyme chai-jsx mocha jsdom jsdom-global
Y ahora crearemos nuestro primer test para el componente Users:
Ahora debemos añadir un script a nuestro package.json para ejecutar mocha con las dependencias y estaremos listos para ejecutar nuestros tests:
// ./package.json
...
"scripts": {
"test": "NODE_ENV=test mocha -r jsdom-global/register --compilers js:babel-core/register \"./js/components/__tests__/*.jsx\""
},
...
Y un archivo más para Babel para que interprete nuestro código:
// ./.babelrc
{
"presets": ['es2015','react']
}
Ya podemos ejecutar el siguiente script para nuestros tests:
npm test
Como puedes ver hay muchos detalles que abarcar con React sobre todo, si vienes de Backend, como yo. Mi intención es que tengas un punto de vista de cómo trabajar con React y si te gusta sigas explorando y aprendiendo. Para ello, te sugiero que empieces por la documentación que ofrece Facebook, continues viendo que es Flux y Redux y luego no te olvides de conocer lo último de React: React Fiber.
Si crees que he olvidado algo importante, tienes alguna sugerencia o tienes alguna duda, déjame un comentario.
Aquí te dejo el repositorio con el ejemplo completo: Repositorio Ejemplo
Espero que te haya resultado de ayuda y que te haya animado a seguir conociendo ReactJS.
Mil gracias a Asier e Isra por las revisiones, moláis un puñao y lo sabéis.