React es tendencia actualmente. Todos hablan de componentes, de Facebook y de cómo son las interfaces del futuro. Pero, ¿qué son los componentes? Y lo más importante, ¿por qué y cuándo utilizarlos?
Definitivamente, los componentes están aquí. En 2013, Brad Frost empezó a hablar sobre Atomic design y de como podemos componer estructuras complejas a partir de partes más pequeñas. React, Angular2 y VueJS son buenos ejemplos de frameworks/librerías que implementan este diseño.
Entonces, ¿qué es el diseño basado en componentes?
Es otra manera de resolver el problema de crear interfaces complejas, fiables y fácilmente actualizables. Para ello, dividimos nuestra interfaz en pequeñas partes más específicas y reusables.
¿Qué son los componentes?
I loved React for the same reasons I loved Lego as a kid.
— Dan Abramov (@dan_abramov) 9 de septiembre de 2016
Esta analogía es la mejor manera de entender qué es un componente. Las piezas de Lego son pequeñas, tienen un propósito y pueden ser combinadas para formar estructuras más complejas. Al igual que los átomos.
Cada pieza puede tener variaciones. Una misma pieza puede ser de distinto color o tener transparencia. Estas son las propiedades de nuestro componente.
Si pensamos en una puerta de Lego, está puede estar abierta o cerrada en un instante de tiempo. Este es el estado de nuestro componente.
Las piezas no dependen de las adyacentes. Si colocamos una pieza azul y una verde al lado, la azul no se ve afectada de ninguna manera. Los componentes son independientes, solo dependen de sus propiedades y su estado.
Si hemos diseñado y desarrollado un ladrillo, luego podremos utilizar tantos ladrillos como nos haga falta. Los componentes son reusables.
Además, podemos coger piezas básicas, como una puerta y varios ladrillos y formar una casa. Del mismo modo, si combinamos varias casas tendremos una ciudad. Creamos estructuras complejas por composición.
Cómo véis, hasta ahora no he hablado en ningún momento de una implementación concreta. Nada de React, VueJS o Angular2. Cada una de ellas implementa este diseño a su modo, pero todas coinciden en las mismas bases. A modo de resumen, cada componente:
- Tiene un estado y unas propiedades
- Es independientes
- Es reusable
- Es pequeño y específico
React
React es una librería de alto rendimiento para el desarrollo de interfaces de usuario. React mantiene un Virtual DOM con la definición, estado y propiedades de los componentes. Este Virtual DOM está conectado con el DOM real, de manera que cada elemento tiene una representación visual.
Si analizamos un poco más la afirmación anterior, vemos que la representación real y la estructura de componentes de React están separadas. Esto es muy importante ya que al diferenciar estas partes, podemos convertir el Virtual DOM a otra representación distinta de HTML. Gracias a esto tenemos proyectos como React Native que nos permite crear aplicaciones móviles nativas a partir de código de React.
Los componentes de React son realmente reusables, ¿cierto? 😉
Componentes en React
Vamos con nuestro primer componente en React (JSBin).
* Mi primer componente en React!
*/
class MiPrimerComponente extends React.Component {
/**
* Renderizamos la vista
*/
render() {
// JSX Syntax
return <h1>React Rocks!</h1>;
}
}
// Ahora necesitamos montar toda la aplicación en un nodo HTML.
// Para ello obtenemos dicho nodo
var node = document.getElementById("content");
// ReactDOM es la librería que renderiza nuestra aplicación en HTML.
ReactDOM.render(<MiPrimerComponente />, node);
// Voila!
Ahí va nuestro primer componente. El método render se encarga de definir su representación visual. React utiliza la sintaxis JSX para la definir etiquetas de HTML. Esta sintaxis es completamente opcional, ya que este código se traduce al método React.createElement. No obstante, os recomiento utilizar JSX ya que os será mucho más sencillo escribir vuestra aplicación.
// Código final:
React.createElement(
"h1",
null,
"React Rocks!"
);
Una vez que tenemos nuestro primer componente, vamos a probar a definir un botón. Este recibirá un título y un método que se ejecutará cada vez que se reciba el evento onClick.
* Este botón no tiene estado.
*/
function MiBoton(props) {
return <button onClick={ props.onClick }>{ props.title }</button>;
}
Al no tener estado, podemos obviar la clase y definir el componente como una función que retorna una vista. Estos componentes son conocidos como stateless. Ahora vamos a incluirlo en nuestro ejemplo anterior (JSBin).
* Mi primer componente en React!
*/
class MiPrimerComponente extends React.Component {
/**
* Renderizamos la vista
*/
render() {
// JSX Syntax
return <div>
<h1>React Rocks!</h1>
<MiBoton title="Boton 1" />
<MiBoton title="Boton 2" />
<MiBoton title="Boton 3" />
</div>;
}
}
Cómo hemos visto, los componentes pueden reutilizarse siempre que lo necesitemos. Cada uno tiene un título, estado y ciclo de vida diferente. Modificar el estado o las propiedades de uno no afecta a los demás.
Nos queda agregar un comportamiento a los botones. Por ejemplo, cada uno de ellos va a sumar una cantidad a un resultado global. Para almacenar este resultado utilizamos el estado de MiPrimerComponente, ya que todos los botones son hijos de este.
(JSBin).
* Mi primer componente en React!
*/
class MiPrimerComponente extends React.Component {
/**
* Inicializa el estado
*/
constructor(props) {
super(props);
// Es necesario ejecutar el método bind para que this se inicialice
// correctamente dentro del método onChange
this.onClick = this.onClick.bind(this);
// Estado inicial
this.state = { result: 0 }
}
/**
* Actualiza el estado
*/
onClick(suma) {
// Fuera del constructor siempre debemos de utilizar setState para
// actualizar el estado.
this.setState({ result: this.state.result + suma });
}
/**
* Renderizamos la vista
*/
render() {
let self = this;
// JSX Syntax
return <div>
<h1>React Rocks!</h1>
<MiBoton title="+ 1" onClick={ function(){ self.onClick(1)} } />
<MiBoton title="+ 2" onClick={ function(){ self.onClick(2)} } />
<MiBoton title="+ 3" onClick={ function(){ self.onClick(3)} } />
<p>Result: { this.state.result }</p>
</div>;
}
}
Del mismo modo podemos reutilizar MiPrimerComponente en otros. Formar una interfaz en base a pequeñas piezas nos ayuda reutilizar código y a estructurar mejor nuestra aplicación (JSBin).
De hecho, el secreto de construir grandes estructuras de manera eficiente es en general, evitar construirlas así en primera instancia. En vez de eso, construyelas con pequeñas piezas muy específicas. - Addy Osmani (Ingeniero en Google)
* Componente principal
*/
class MiAplicacion extends React.Component {
// Renderizamos varios MiPrimerComponente
render() {
return <section>
<MiPrimerComponente />
<MiPrimerComponente />
<MiPrimerComponente />
</section>;
}
}
Rendimiento en React
Antes he definido React como una librería de "alto rendimiento". El secreto de este rendimiento de React reside en el proceso que calcula los cambios de la interfaz en cada interacción. Este proceso es conocido como Reconciliación.
React's key design decision is to make the API seem like it re-renders the whole app on every update
- React Team
Cada interacción afecta aparentemente a toda la interfaz. Pero no es así. React calcula las diferencias mínimas entre el Virtual DOM actual y el siguiente. De este modo, sólo se modifican ciertos componentes, reutilizando todos el máximo posible. Esta es la clave del rendimiento de React.
Componentes (React) everywhere
El diseño de componentes es un modelo para incluir en nuestra navaja suiza de desarrolladores. No obstante, no todo proyecto tiene que tener una interfaz basada en este diseño.
Este modelo cobra sentido en aplicaciones complejas. La curva de desarrollo en este caso es más acentuada al principio, ya que tenemos que definir todos estos componentes básicos. Sin embargo, a medida que pasa el tiempo y la aplicación crece, el esfuerzo de desarrollo se va reduciendo.
Otra ventaja es que podemos reutilizar los componentes en otros proyectos. Por ejemplo, si diseñamos una librería de componentes en nuestra empresa, el esfuerzo inicial de desarrollo de la interfaz de nuevos productos se reduce considerablemente.
El diseño de componentes no es la solución definitiva, pero es una gran manera de abordar la creación de interfaces complejas. A su vez, React es una buena implementación con una gran comunidad detrás. Con todas estas piezas, parece que ha llegado el momento de empezar a pensar en componentes 🙂