El concepto de componente es algo bastante sencillo de entender, básicamente se trata de un elemento software visual que tiene su propio estado, recibe unas propiedades e implementa su propia lógica de renderizado. Pero… ¿todos los componentes son iguales? ¿Podemos jerarquizarlos o diferenciar en tipos de componentes?
Este articulo trata de ser un recorrido por los tipos de componentes que podemos usar en React. Vamos a diferenciar los tipos en dos categorizaciones, la categorización por comportamiento y la categorización estructural.
Tipos de Componentes de Comportamiento
En función del tipo de comportamiento que vaya a realizar el componente podemos diferenciar los componentes en Stateless, Statefull, PureComponents o HOC. Vamos a conocer y entender cada uno de estos tipos de componentes:
Stateful Component
Este tipo de componentes son los mas utilizados. Las principales características de este tipo de componentes es que utilizan la encapsulación en clases, tienen un estado que definen, y actualizan y cada cambio tanto en props como en estado llaman al método render.
class MiBoton extends React.Component { constructor(props) { super(props); this.style = { background: 'blue', color: 'white' }; } render () { return ( <button {...this.props} style={this.state.styles} /> ); } }
Componentes Stateless
Estos componentes son una versión simplificada del componente más común: el Stateful. Este tipo de componentes se definen como funciones en vanilla js y no tienen ni trabajan con estado. Los únicos datos con los que trabajan este tipo de componentes es con las props recibidas, además no permite trabajar con sobrescribir los métodos de su ciclo de vida. Las ventajas de este tipo de componentes es que son sencillos de escribir, fácilmente testeables y mejoran el rendimiento.
Aquí os dejo un ejemplo de componente statless:
const MiBoton = props => { const styles = { background: 'blue', color: 'white' } return ( <button {...props} style={styles} /> ) }
Acerca de este tipo de componentes os aconsejo la lectura de este artículo donde se destacan todas las características y ventajas que poseen los Stateless Components:
Pure Component
Este tipo de componentes es similar a los stateful en cuanto a su definición. También se implementan como clases, pero en este caso van a extender de React.PureComponent. Al igual que los componentes stateless este tipo de componentes no definen un estado, siendo puramente solo un componente visual. Este tipo de componentes están optimizados para una mayor performance de renderizado, ya que solo cambian si detectan un cambio en sus props y estos son distintos a los valores anteriores.
La implementación es idéntica que el Statefull, únicamente que nos contienen estado y extienden de React.PureComponent.
class MiBoton extends React.PureComponent { const styles = { background: 'blue', color: 'white' } render () { return ( <button {...this.props} style={styles} /> ); } }
Componentes de Órden Superior u HOC.
Este tipo de componentes es un patrón de diseño utilizado en las aplicaciones React. Este patrón de diseño llamado de otra manera en este ecosistema me recuerda fielmente al patrón Decorator ( https://sourcemaking.com/design_patterns/decorator/php)
Los Componentes de Orden Superior (HOC) son funciones que toman como parámetro otro componente, extendiendo su funcionalidad y devolviendo un nuevo componente con funcionalidad extendida. Si las propiedades del HOC cambian, este se renderizará de nuevo y actualizará el componente envuelto en él.
Este tipo de componentes se usan para implementar funcionalidades comunes como pueden ser la paginación, interceptar y modificar la renderización, hacer llamadas a apis y alimentar el componente envuelto, control sobre los inputs de formularios…
Este tipo de componentes se usa en librerías muy utilizadas en el ecosistema React como son react-redux y react-redux-form. Básicament es un buen método para desacoplar funcionalidad, extender la funcionalidad de nuestros componentes y reutilizar el código en toda en nuestra aplicación
Vamos a ver un ejemplo extraído de Intenet en el que se realiza un HOC TruncateHOC que es responsable de truncar la propiedad text de un componentes y truncarla a 25 caracteres como máximo.
const TruncateHOC = WrappedComponent => class extends React.Component { static propTypes = { text: React.PropTypes.string.isRequired }; truncateText(text) { const maxLength = 25; if (text.length > maxLength) { return `${ text.substring(0, maxLength - 3) }...`; } else { return text; } } // Renderizamos el componente render() { // Creamos una copia de los props actuales let props = Object.assign({}, this.props); // Modificamos el texto props.text = this.truncateText(props.text); // Renderizamos el componente principal return <WrappedComponent { ...props } />; } };
Una vez se ha definido el HOC, se puede empezar a utilizar en todos los componentes que necesitemos. En este caso deben de cumplir con la interfaz especificada en el HOC y es que deben de tener una prop text.
let Description = props => <p>{ props.text }</p> class Article extends React.Component { render() { return <article>{ this.props.text }</article> } } // Se aplica el HOC! Description = TruncateHOC(Description); Article = TruncateHOC(Article);
Existen varios artículos que hablan en profundidad de este tipo de componentes, ya que son los que requieren mayor complejidad y atención a la hora de implementarlos. Os dejo un listado de URLs donde se detalla el porqué de este tipo de componentes, y ejemplos de uso:
- https://reactjs.org/docs/higher-order-components.html
- https://medium.com/@mappmechanic/react-utility-higher-order-components-as-decorators-tc39-stage-2-9e9f3a17688a
- https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e
- https://blog.builtbyedgar.com/hoc-o-componentes-orden-superior-en-react/
Tipos de Componentes estructurales
Estos tipos de componentes no corresponden técnicamente con ningún elemento de la API, clase o función en React, son simplemente puramente conceptuales . El propósito de esta categorización es organizar nuestra aplicación para que sea más sencilla e intuible de desarrollar. Esta categorización no es un estándar de React si no de la comunidad y permite definir una arquitectura en nuestras aplicaciones.
Componentes Visuales
Conocidos en inglés como Presentational Components. Este tipo de componentes solo deben centrase y enfocar sus esfuerzos en como debe renderizarse la UI. Este tipo de componentes puede componerse de otros elementos visuales y suele incluir estilos y clases. Todos los datos implicados en su renderización se deben recibir a través de props, por lo que deben ser independientes de llamadas a servicios externos. Este tipo de componentes suelen ser de tipo Stateless ya que no necesitan estado, y deben de gestionar las acciones pasándoselas a componentes padre a través de sus props.
Ejemplo:
class Item extends React.Component { render () { return ( <li><a href='#'>{ this.props.valor }</a></li> ); } }
Componentes Contenedor
Conocidos en inglés como Container Components. Estos componentes deben de dejar a un lado la interfaz y encargarse de la parte funcional, simplemente son contenedores de otros componentes y se encargan de gestionar la lógica de interacción y la lógica de los datos, haciendo las llamadas necesarias a servicios externos. A diferencia de los anteriores suelen gestionar su propio estado, siendo un nodo importante en la jerarquía del árbol de componentes.
Ejemplo:
class ItemsContainer extends React.Component { constructor (props) { super(props); this.state = { temas: ['Vue', 'React JS', 'Angular'] }; } render () { const items = this.state.temas.map(t => ( <Item valor={ t } /> )); return ( <div> <ul>{ items }</ul> </div> ); } }
Generalmente, los componentes contenedor representan cada una de las páginas y coincide con una de las rutas definidas. Recomendable la lectura de Enrique Munguia.
Conclusión
Hemos realizado un recorrido por la distinta categorización y tipos de Componentes en React. Estas son las tipologías mas usada en cualquier arquitectura SPA basada en React. Te animo a empezar a utilizarlo en tus desarrollos y que nos cuentes tu experiencia a la hora de implementar una arquitectura front en tus proyectos.