En esencia, y con lo que hemos visto, podemos decir que React se basa en crear funciones (componentes funcionales) que tienen lógica Javascript y devuelven código HTML (JSX, el HTML de React). De esta forma, se puede construir toda una página web con React. Sin embargo, falta una de las partes más importantes de React, que es el trabajar con los datos.
Una vez tenemos toda una web construida con componentes funcionales, debemos tener en cuenta que hay datos que son sensibles a cambiar en una web. Por ejemplo, imaginemos campos con información variable (nombres, datos de contacto, etc...), un contador que cambiar al pulsar un botón, etc.
El estado en React
En React, los datos que son sensibles a cambios se denominan estado. Estos datos pueden ser cualquier tipo de dato:
De hecho, los datos con los que trabaja un componente suelen dividirse en dos:
- 1️⃣ Props: Los datos que le pasa un componente padre. No se modifican dentro del componente.
- 2️⃣ Estado: Los datos que son sensibles a cambiar dentro del componente.
Por ejemplo, observa la siguiente imagen. En ella puedes ver como tenemos una aplicación web que tiene el componente main que dentro tiene un componente counter. Si nos centramos en el componente counter, dicho componente tendrá un estado que puede cambiar (el número del contador, por ejemplo, que se incrementa cada vez que pulsas un botón del contador) y algunas props, que son datos que el contador no va a cambiar por si mismo (un nombre para el contador, por ejemplo):
Los re-render de React
En Javascript, cuando hay cambios en los datos no ocurre nada en la interfaz de usuario. De hecho, generalmente manipulamos la lógica y los datos por un lado, y luego tenemos que manejar el DOM para actualizar la interfaz visual de usuario.
En React, la idea es que todo esto se haga de la forma más automática posible:
- 1️⃣ React ejecuta la función de un componente y ejecuta su lógica Javascript asociada.
- 2️⃣ Obtiene las props del componente y gestiona su estado.
- 3️⃣ Finalmente, genera un HTML con el JSX y renderiza (dibuja) la interfaz de usuario.
- 🟨 Si React detecta un cambio en las props o en el estado se efectua un re-render.
Un re-render es una acción donde React vuelve a ejecutar la función del componente y vuelve a renderizar la interfaz de usuario, actualizándola con los nuevos datos que cambiaron y desencadenaron el re-render. De esta forma, la interfaz de usuario siempre se mantiene actualizada con los datos nuevos, sin que el desarrollador tenga que estar haciéndolo manualmente.
Paradójicamente, React es una librería que no es reactiva, sino que sigue un patrón de actualización de cambios parecido a la reactividad, utilizando su Virtual DOM. Si quieres saber más sobre la reactividad, te aconsejo echar un vistazo a este post: ¿Qué es la reactividad?
¿Qué ocurre en un re-render?
Los re-renders que se realizan en una aplicación son ideales para que se actualicen los datos automáticamente y el desarrollador no tenga que escribir tanto código para controlarlo manualmente. Sin embargo, si no se es cuidadoso al escribir nuestro código, se pueden realizar re-renders innecesarios.
Más adelante veremos cuales son las causas más comunes de que se disparen re-renders innecesarios y qué podemos hacer para evitarlos.
Existe una excelente extensión llamada React Scan que permite mostrar visualmente cuando se produce un re-render en alguna parte de nuestra aplicación React.
El virtual DOM de React
Las páginas webs se dibujan en un navegador mediante su código HTML. La estructura de este código se denomina DOM, y es una representación de todos los elementos HTML de la página web. En las aplicaciones React, aunque también se trabaja con el DOM, tenemos una estructura intermedia denominada Virtual DOM.
Este Virtual DOM no es más que una «versión ligera» del DOM real del navegador almacenada en memoria. De esta forma, las aplicaciones React antes de actualizar el DOM real, consultan ese Virtual DOM y realizan los cambios de forma más ágil en él, actualizando posteriormente el DOM real sólo cuando sea estrictamente necesario.
El proceso de trabajo de React suele ser el siguiente:
- 1️⃣ Se ejecuta la función de un componente y se genera un Virtual DOM con el estado actual.
- 2️⃣ Si hay cambios en el estado o props, se crea un Virtual DOM parcial con sólo los cambios.
- 3️⃣ Se comparan los cambios de ese Virtual DOM parcial con el Virtual DOM anterior (diffing).
- 4️⃣ Se actualiza el DOM real sólo con los nodos que hayan cambiado (reconciliación).
De esta forma, al trabajar con React, la interfaz gráfica de usuario se actualiza sola al modificar los datos. No hay necesidad de hacer cambios en el DOM de forma manual.
Mito: El DOM real es lento
Hay que tener mucho cuidado con una afirmación muy extendida que dice que «el DOM es lento, el virtual DOM es más rápido». Esto es una simplificación que puede llevar a conclusiones erróneas.
Desglosemos en varios casos para que se entienda la puntualización:
- ❌ El DOM real es lento.
- ✅ Un uso ineficiente del DOM por parte del desarrollador puede ser lento.
- ✅ Los desarrolladores no suelen trabajar eficientemente con el DOM.
- ❌ El Virtual DOM es más rápido que el DOM real.
- ✅ El Virtual DOM hace más fácil para el desarrollador trabajar con el DOM.
- ✅ Con el Virtual DOM no debes preocuparte tanto de la gestión del DOM.
Existe un artículo muy interesante de Rich Harris (creador de Svelte) donde habla precisamente de este tema y de como se originó este mito: Virtual DOM is pure overhead.