Este post asume que estás familiarizad@ con la creación de un proyecto React. Si no es así, te sugiero leas este post primero
Introducción
ReactJS se presenta como una librería reactiva, declarativa y basada en componentes.
La idea, por tanto, es que pensemos en nuestras vistas como un conjunto de pequeñas partes capaces de contener valores (componentes) que se combinan para crear porciones del total de la vista que tienen la capacidad de modificarse de forma dinámica (reactiva).
Los nombres de los componentes y las funciones utilizadas para modificar los valores que contienen deben ser lo más descriptivos posible para que, sin necesidad de leer cómo, seamos capaces de entender qué hacen (declarativa).
Para lograrlo, se aplican tres conceptos: Componente, State y Props y VirtualDOM.
Componente
El concepto de Componente en React es una adaptación de los Componentes Web, por lo que es imprescindible primero entender estos para luego hablar de aquellos.
Los Componentes Web son un paquete de diferentes tecnologías que te permiten crear elementos personalizados reutilizables — con su funcionalidad encapsulada apartada del resto del código — y utilizarlos en las aplicaciones web.Mozilla MDN
¿Qué quiere decir esto? Básicamente, implica usar JavaScript para generar objetos que contengan valores que usaremos para insertar en el DOM (Document Object Model) nodos que indiquen qué etiqueta HTML, con qué contenido y propiedades CSS se debe mostrar en la ventana del navegador.
Un Componente en React, entonces, es un elemento capaz de contener información y generar una vista en la ventana del navegador.
En React se pueden crear dos tipos de Componente: los Componentes de Clase y los Componentes Funcionales
Componente de Clase |
Componente Funcional |
En la actualidad, el trabajo con React se hace íntegramente a través de Componentes Funcionales pero para entender cómo es esto posible (y por cuestiones de compatibilidad con proyectos anteriores) vamos a explicar los dos tipos de Componentes.
Componente de Clase
Más arriba definimos a los Componentes como elementos que tiene su funcionalidad aislada del resto de los elementos. Esta funcionalidad es la que maneja qué vista se va a estar mostrando en la ventana del navegador.
React surgió en el año 2013 como una librería que ofrecía la posibilidad de automatizar el funcionamiento de los Componentes y, para lograrlo, creó los Componentes de Clase.
Un Componente de Clase se caracteriza por utilizar el concepto de Clase proveniente de la Programación Orientada a Objetos para poder almacenar un objeto especial denominado state.
El objeto state es usado por React para saber cuándo hay que cambiar la vista. Es decir que, al momento de generar la funcionalidad de nuestros Componentes, lo que buscamos es modificar los valores almacenados en el state para que React actualice la vista en la ventana del navegador.
Los Componentes de Clase son los únicos que tienen la capacidad de almacenar al objeto state.
Componente Funcional
Debido a la naturaleza de la librería, y al hecho de que un Componente Funcional no es capaz de almacenar al objeto state, durante mucho tiempo existió una división entre los usos de los Componentes.
Los Componentes de Clase albergaban la lógica de modificación de state y el almacenamiento de los datos a mostrar y los Componentes Funcionales, denominados así porque se crean utilizando funciones, se encargaban del trabajo de renderizado y toda la lógica pertinente.
A partir de la versión 16.8 (año 2019), y gracias a la aparición de los Hooks, es posible producir un Componente Funcional que tenga la capacidad de avisarle a React que es necesario actualizar la vista, es decir, aplicar el funcionamiento del objeto state.
Es de suma importancia entender que el uso de los Hooks, bajo ningún concepto, implica que los Componentes Funcionales tengan la capacidad de almacenar objeto state. Eso es algo que solo pueden hacer los Componentes de Clase. Aunque lo cierto es que, gracias a los Hooks ya no tenemos la necesidad de crear un Componente de Clase para poder aplicar lógica de modificación y almacenamiento de datos. Esto demostró ser una gran ventaja para los usuarios de la librería porque, como escritores del Lenguaje JavaScript, el tener que escribir Componentes de Clase era algo a lo que no terminábamos de acostumbrarnos.
¿Cómo trabajan los Componentes?
Todos los Componentes se pueden dividir en dos partes: la lógica de datos y el renderizado de los mismos.
La lógica de datos son las funciones/variables que vamos a utilizar para generar datos, mientras que el renderizado es la creación de los elementos que queremos mostrar.
El trabajo con la lógica de datos está sumamente ligado al state y las props aunque es posible crear lógica de datos que no los use.
El renderizado lo logramos trabajando con JSX y CSS.
Todos los Componentes deben tener un return (los Componentes de Clase deben tener una función render para este return), en el que podamos agregar nuestro código JSX (recordemos que JSX nos permite escribir elementos de React como si estuviéramos trabajando con HTML).
Algo a tener en cuenta cuando trabajamos con JSX en el return es que ninguna función (y sí, los Componentes son funciones) tiene la capacidad de retornar más de un elemento.
Si deseamos hacer una vista con varios elementos, es necesario crear un contenedor div (<div>…</div>) o un fragmento (<>…</>) y dentro agregar todos los elementos deseados.
Además, para agregar clases de CSS hay que emplear el “atributo” className.
Antes de ver cómo trabajar con el state y las props te invito a que te animes a crear las primeras vistas usando Componentes de React.
State y Props
Como ya dijimos, el state es el objeto state elemento pensado para desencadenar la reacción de la librería React y así mantener actualizada la vista en el navegador con los datos almacenados.
Ahora bien, el objeto state (o la funcionalidad del mismo que podemos emular utilizando Hooks) solo es visible y accesible desde el Componente que lo contiene.
Anteriormente, hablábamos de la división de uso que existía entre los Componentes de Clase y los Componentes Funcionales. Pero si los valores almacenados en el objeto state únicamente pueden ser empleados en el Componente que lo contiene ¿Cómo es posible que un Componente Funcional pueda generar una vista a partir de esos valores?. Para eso existen las props.
La props son un objeto al que todos los Componentes de React, por el simple hecho de serlo, tienen acceso. En este objeto se almacenan valores que otros Componentes quieren compartir. De esta forma, entonces, un Componente de Clase (o un Componente Funcional usando Hooks), crea y almacena valores de state y los comparte con otros Componentes a través de las props.
Para crear una prop, el Componente que desea compartir algún valor debe estar renderizando el Componente que va a recibir ese valor (con JSX agregamos una etiqueta autoconclusiva al return que todo Componente debe hacer).
Al elemento renderizado hay que agregarle un “atributo” con un nombre que nos permita identificar la prop en el Componente que la recibe.
El Componente que recibe la prop, si es un Componente Funcional, debe indicar el valor props como parámetro de la función. Este parámetro va a almacenar todos los valores que recibe el componente en un objeto que utiliza el nombre del “atributo” creado al momento de renderizar para generar la clave que contendrá el valor que buscamos recibir.
Valor de State pasado por Prop (Componente Clase → Componente Clase) |
Valor de State pasado por Prop (Componente Clase → Componente Funcional) |
Hook useState
Los Hooks son funciones especiales que permiten la utilización de lógica relacionada con los Componentes. Gracias a ellos, los Componentes Funcionales son capaces de replicar las acciones anteriormente reservadas para los Componentes de Clase.
El primero de los Hooks que nos encontramos es el useState. Con este Hook podemos emular el comportamiento del objeto state, es decir, que vamos a poder almacenar valores que le indican a React cuándo es momento de cambiar la vista.
useState es una función que toma un valor y retorna un array de dos elementos. El primero es el valor que le pasamos cuando la usamos (este valor es conocido como state inicial) y el segundo es una función que nos permite modificar el state inicial.
Valor de State generado con Hook pasado como Prop |
VirtualDOM
A lo largo de este artículo venimos desarrollando la idea de que el trabajo de React es reaccionar a los cambios en el objeto state para mantener la vista del navegador sincronizada con los datos almacenados en el mismo. Para lograrlo, la gente de Facebook creó el VirtualDOM y, para entender qué es, vamos a empezar por hablar del DOM.
DOM
El Document Object Model, más conocido como DOM, es la API Web que nos permite manipular la vista del navegador desde JavaScript. Para ello, crea el denominado DOMTree.
El DOMTree es un mapa de las relaciones entre los distintos elementos declarados en el documento HTML. Cada etiqueta, con su respectivo contenido y atributos, queda debidamente representada mediante los nodos del DOMTree.
Cuando usamos JavaScript para agregar contenido o modificar una etiqueta, lo que hacemos es modificar el nodo correspondiente dentro del DOMTree. Esta es la razón por lo que es posible que el documento HTML no tenga escrito todo lo que estamos visualizando en la ventana del navegador.
Trabajo del DOM |
La manipulación del DOM, entonces, permite la creación de vistas dinámicas a través de la programación con JavaScript. Sin embargo, es importante entender que esto conlleva un alto costo en términos de consumo de recursos, por lo que existe una regla de oro que todo programador de JavaScript debe conocer: "Reducir al máximo la cantidad de modificaciones al DOM".
virtualDOM
La idea de usar React es tener la capacidad de desarrollar Interfaces de Usuario (UI) dinámicas y consistentes. Una UI está constantemente manipulando el DOM para asegurarse que el usuario vea los datos actualizados, lo que significa que consume muchos recursos. El virtualDOM es una solución a ese problema.
Cuando escribimos Componentes, estos se agregan al árbol de virtualDOM con los valores que usamos cuando los declaramos. Una vez que React leyó todos los Componentes y armó el árbol, se lo pasa al DOM para que este se encargue de generar la vista.
Toda la lógica de manipulación de vista que usamos en los Componentes afecta al árbol del virtualDOM y este es el encargado de manipular el DOM.
En este punto es importante destacar que la creación de virtualDOM arranca en el archivo index.html que create-react-app genera dentro de la carpeta public. En el artículo Introducción a ReactJS hablamos sobre el conjunto de herramientas que permiten el trabajo con la librería React. Entre ellas se encuentra Webpack, encargada de combinar el código HTML, CSS y JS para generar los archivos que, finalmente, serán subidos a nuestro servidor.
El archivo index.html es el que usa Webpack como base para el armado de la web. Es decir, ese archivo es el equivalente a cualquier archivo index.html que creamos cuando no trabajamos con estas herramientas. En él se puede encontrar, entre otras cosas, un div con el atributo id="root". Ese es el nodo que se va a utilizar para insertar las vistas creadas con React.
Relación entre VirtualDOM y DOM |
Es probable que en este punto te estés preguntando cuál es la necesidad del VirtualDOM si hace, esencialmente, el mismo trabajo que el DOM. La respuesta a esa pregunta la encontramos en la regla de oro de la manipulación del DOM.
El VirtualDOM tiene como trabajo reconocer cuáles son los valores de state que se modifican producto de la interacción con el usuario, modificar todos los nodos que se vean afectados (todos los Componentes que usan ese valor a través de sus props) y pasarle al DOM esos nuevos valores. Este proceso reduce considerablemente el consumo de recursos, ya que es el VirtualDOM el que realiza todas las tares más pesadas para que el único trabajo del DOM sea la generación de la vista.Conclusión
Trabajar con React implica la creación de Componentes que pueden contener un valor de state. Esos Componentes, y sus valores de state, son usados por el VirtualDOM para generar el árbol de nodos que se le pasa a DOM quién, finalmente, es el encargado de generar la vista en la ventana del navegador.
Redes