Meteor + React
En mi anterior entrada, Nodejs fácil con Meteor, hicimos una introducción a Meteor y lo fácil que es empezar un desarrollo Nodejs con este.
En esta historia vamos a utilizar Meteor + React para hacer una breve introducción a React. Ajustaremos el ejemplo del contador Meteor + Blaze.
No soy muy versado en estos asuntos técnicos, encontrarán una explicación muy natural, espero logren entenderme.
React
React es una librería frontend escrita en JavaScript por Facebook, excelente alternativa para construir interfaces de usuario interactivas.
Con React creamos view component (componentes) que gestionan su propio estado, esto es, si solo una vista tuvo cambios entonces solo cambia esta vista y no todo el DOM. Pero además React tiene algo llamado DOM Virtual donde cualquier cambio se hace primero en este DOM Virtual y cuando está listo lo pasa al DOM Final.
Esto genera un proceso de mínimos cambios que en ultimas es más eficiente en comparación a lo tradicional en otras librerías de este tipo. Y precisamente esta es la gran diferencia en relación con las librerías de templates.
Entonces en las librerías de templates (por ejemplo Blaze) escribimos HTML con elementos personalizados o propios de cada librería y JavaScript, tras bambalinas, llama, lee y procesa estos elementos, después envía y transforma en el DOM.
En la otra mano, los componentes en React se escriben enteramente en JavaScript con el HTML aquí mismo, pasa al DOM Virtual y de aquí al DOM final.
React utiliza una sintaxis que luce similar a XML, llamada JSX. Se sugiere escribir los componentes separadamente en archivos con extensión .jsx (aunque esto es opcional, se puede escribir en .js), el cual posteriormente se compila para convertir en JavaScript.
React implementa el método render() que toma datos de entrada y retorna lo que quieres mostrar. Los datos de entrada que son pasados al componente pueden ser accedidos por render() a través de this.props. El componente también puede mantener los datos de estado interno a los cuales se accede a través de this.state.
Los componentes React tienen, por supuesto, muchos más métodos, no es el objetivo explicar aquí en este momento, así que pueden ver la documentación de React y además este excelente tutorial de Meteor con React.
Otro ejemplo que hace muy poco
Entonces el ejemplo de plantilla Blaze que Meteor nos da al momento de crear un nuevo proyecto lo vamos a adaptar a React.
Nuevamente recordar que este ejemplo no hace mucho, pero nos permitirá introducirnos en React y lograr diferenciar entre una Plantilla Blaze y un Componente React. Ah, una última cosa antes de continuar, voy a ir paso a paso, si eres novato lo apreciarás.
A la consola de comandos y en donde tengas tus proyectos Meteor vamos a crear un nuevo proyecto:
meteor create myCounterApp
cd myCounterApp
meteor
Vamos a instalar React en nuestro proyecto, como estamos con Nodejs entonces usaremos npm:
npm install --save react react-dom
En el anterior comando instalamos vía npm dos módulos: react y react-DOM y de paso guardamos en el archivo package.json estas dependencias.
En este ejemplo trabajaremos todos nuestros archivos en el directorio /client.
En nuestro editor favorito pasamos a editar los archivos, empecemos por client/main.html:
<head>
<title>Mi Counter Meteor + React</title>
</head><body>
<div id="hello"></div>
</body>
Hemos borrado los templates «hello» e «info» al igual que todo lo contenido en el tag <body>: <h1> y los data context {{> hello}} e {{> info}}.
En el <body> en su lugar se agrega un contenedor con un id=“hello” (<div id=“hello”></div>)que usaremos posteriormente con React.
Borramos el archivo client/main.js y creamos uno nuevo client/main.jsx.
Como en la anterior historia, vamos a usar React con la sintaxis ES6 de una, sin titubeos.
Lo primero que haremos es importar React, así como Meteor y el método render() del modulo react-dom:
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
Declaramos entonces una subclase (view component) Counter que será una extensión de la clase Component de React y usaremos su constructor para ajustar unos estados iniciales:
class Counter extends React.Component { constructor(props) {
super(props);
this.state = {count: props.initialCount};
this.tick = this.tick.bind(this);
}
...}
Aquí, algo de ES6:
- En nuestra subclase (la clase padre es Component de React) con constructor se crea e inicia el componente con sus propiedades (props) las cuales se extienden a su padre con super(props).
- Se asigna al estado del componente this.state la propiedad count con un valor inicial que se ajustará más adelante props.initialCount.
- Una propiedad tick apuntará a un método tick() que creamos más adelante.
Continuamos…
Creamos un método tick() (modifique el método counter() original por este tick() y el objeto reactivo counter por la propiedad count para más claridad) que ajustará el estado del conteo actual + 1:
tick() {
this.setState({count: this.state.count + 1});
}
Ahora viene el método render() de nuestro componente, el cual retornará lo que queremos que se renderize al DOM:
render() {
return (
<div>
<h1>Welcome to Meteor!</h1>
<button onClick={this.tick}>Click Me</button>
<p>You’ve pressed the button {this.state.count} times.</p>
</div>
);
}
Vemos como React ajusta en el onClick la propiedad tick. Esta propiedad contiene el método tick() que se encarga de tomar el estado de count y sumarle 1 para posteriormente actualizarlo.
Recuerden que count al momento de inicializar el componente se le dijo que tendría un valor inicial, así que antes de pasar a ver el resultado final, queremos definir el tipo de datos para nuestra propiedad props.initialCount y un valor inicial para este, lo cual definiremos al final del código por fuera de la subclase:
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };
Ahora sí, Meteor se encarga del resto:
Meteor.startup(() => {
render(<Counter />, document.getElementById('hello'));
});
Esto último es muy simple, el método Meteor.startup() [que corre un código cuando el client o el server inician], corre el método render() de react-dom, el cual llama a nuestra clase Counter (el componente). El resultado lo ubica en el elemento con el id “hello” del DOM osea <div id=“hello”></div> que esta en client/main.html.
El código final quedaría así:
Les dejo el código completo en github para facilidad pero no van tener mucho problema con este asunto. Compárenlo con el de Meteor + Blaze para ver las diferencias.
He sido un poco explícito con este breve código y me alargue más de lo que quería, pero espero que halla servido para entender algo de cómo funciona React. Hay mucho más detrás de todo esto, lo dejo para que lo descubran por su propia cuenta.
Para tener presente: en el método render() de nuestra subclase en el return() solo debe haber un único contenedor padre y dentro de este lo que queramos ubicar allí.
Conclusiones
React es muy interesante por sí solo pero con Meteor parece que encontró la horma a su zapato. Aunque más bien Meteor encontró la horma perfecta y le dejó el trabajo de los views a Facebook, trabajo que es bienvenido.
Notarán que a diferencia de un proyecto Nodejs + React, en nuestro proyecto Meteor + React ni nos hemos preocupado por el empaquetado, interpretes, la salida ni otros que nos desvían del objetivo inicial que es aprender React y crear algo que funcione fácil en Nodejs. Entonces mucho de razón tenía cuando dije que Nodejs es fácil con Meteor.
Quiero saber si esto ha servido, si te queda tiempo escríbeme a ver si me incentivo a continuar más pronto de lo planeado el proyecto prometido: Meteor + React + MaterialUI + Mongodb. ¡Gracias!