Construye tu propio (Simple) React desde cero!

Rate this content
Bookmark

¿Alguna vez te has preguntado cómo funciona React?

¿Cómo sería crear las líneas mágicas que componen la herramienta que todos aprendimos y amamos?

Acompáñanos en nuestro viaje para implementar React desde cero, haciendo que un proyecto React simple funcione con tu propia biblioteca my-react.js.


Qué incluye

- Introducción

- Renderizando nuestro primer componente

- Ciclo de actualización y el VDOM

- Conoce los hooks


Requisitos previos

- Algunos conocimientos de React.

112 min
28 Nov, 2022

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Este taller se centra en la creación de una aplicación React desde cero y abarca temas como la renderización de componentes, el manejo del estado y la optimización de la renderización. Proporciona instrucciones paso a paso y un repositorio de GitHub con un caso de prueba y código de plantilla. El taller también explora el uso de hooks, como useState y useEffect, para la gestión del estado y el manejo de efectos secundarios. La implementación incluye un módulo de diferencias para optimizar la renderización identificando los elementos específicos que requieren actualizaciones. En general, el taller ofrece una comprensión integral del desarrollo de React y proporciona ejemplos prácticos para construir una aplicación React.

Available in English

1. Introducción al Masterclass de React

Short description:

Hoy en este masterclass estaremos creando nuestro propio React desde cero. Cubriremos los conceptos básicos de React, renderización de componentes, manejo de estado, diffing y actualizaciones específicas. Tenemos un repositorio en GitHub con una aplicación de lista de tareas como caso de prueba y un boilerplate para tu propia versión de React. El proceso es paso a paso con ramas para cada paso y soluciones disponibles. Las preguntas se pueden hacer en el canal de Discord. Clona el repositorio, navega a la terminal, abre el repositorio en tu editor de texto y sigue las instrucciones en el archivo leeme. React es una biblioteca declarativa de JavaScript basada en componentes que utiliza props para pasar datos a través de la aplicación.

¡Entendido! Sí, para aquellos que se acaban de unir, hoy en este masterclass estaremos creando nuestro propio React desde cero. Entonces, ¿cómo lo vamos a hacer? El programa para hoy es un masterclass de tres horas, así que agradezco tu tiempo y también tu paciencia. Comenzaré con una breve introducción y luego veremos algunos conceptos básicos de React rápidamente y luego pasaremos a, este masterclass está dividido en cuatro capítulos, donde el primer capítulo se centrará en cómo renderizar componentes en nuestra introducción al DOM virtual, que es una parte clave de React, cómo manejamos el estado. El segundo capítulo, luego el capítulo tres tratará sobre el diffing y cómo apuntar actualizaciones para un componente específico en lugar de renderizar toda la aplicación y luego nuestro último capítulo, veremos el useEffect específicamente. Tenemos algunos rezagados más. Esta es una parte importante de este masterclass. Hemos creado un repositorio en GitHub para ti. Y este repositorio contiene dos cosas, una aplicación simple de lista de tareas en React para agregar elementos a tu lista de tareas, no modificarás eso, pero el repositorio también contiene un boilerplate para tu propia versión de React, que es lo que editaremos. Y el objetivo al final del masterclass es tener todas las características de la aplicación de lista de tareas funcionando con tu propia versión de React. Y el proceso es paso a paso. Hemos creado ramas para cada paso, que también contienen las soluciones para el paso anterior. Es un enfoque iterativo y espero que sea bastante fácil de seguir. Y si no, tienes las soluciones disponibles en el siguiente paso. Y si tienes preguntas, te pedimos que no las hagas aquí. Sino en el canal de Discord, al que deberías tener acceso. Tal vez pueda dejar el enlace en caso de que no lo tengas. Lo agregaré al chat. Puedo encontrar el chat. Lo dejaré en el chat después. O tal vez, Zsányi, puedes ponerlo en el chat. Lo primero es lo primero, necesitamos clonar nuestro repositorio. Eso también está disponible en el chat de Discord, proporcioné un enlace. Lo primero es clonar ese repositorio. Así que navega a tu terminal, clónalo, luego navega al directorio y abre el repositorio en tu editor de texto preferido. Y luego todas las instrucciones adicionales están en el archivo leeme. Ese será tu mejor amigo y guía. Y también tenemos documentación bastante extensa en el repositorio, que puede ayudar a cubrir conceptos clave y brindar más información de manera detallada sobre los conceptos que cubriremos en cada paso. Y las diapositivas a partir de este punto se centran en algunos conceptos generales de React. Toda la diversión sucederá en tu propio editor de código.

Entonces, ¿qué es React? React es una biblioteca de JavaScript. Y lo más importante es que es declarativo. Lo que significa que tu código describe qué quieres hacer y no cómo hacerlo. Lo genial de React es que está basado en componentes. Entonces, creas muchos componentes encapsulados que son responsables de su propio estado. Y reciben datos de entrada, que llamamos props. Y está escrito en JavaScript en lugar de un lenguaje de plantillas. Entonces, los datos se pueden pasar fácilmente a través de tu aplicación mediante estas props. Y ayuda a mantener el estado fuera del caos. Y ahora voy a pasar la palabra... Oh, no. Primero, conozcamos el proyecto. Como dije, tenemos una aplicación de lista de tareas, no la modificaremos. Pero la usaremos como nuestro caso de prueba. Así que podrás probar tu progreso. Y sí, utiliza todos los conceptos que estamos tratando de aprender en este masterclass. Y nuevamente, nuestra versión de React. Permítanme que más personas se unan. Entonces, si has clonado el repositorio, solo para aquellos que se han unido, puedes acceder al repositorio de GitHub en el canal de Discord. Y debes clonarlo y luego abrirlo. Pero voy a mostrar rápidamente cómo se ve ese repositorio.

2. Configuración del entorno y actualización de archivos clave

Short description:

Para comenzar, cambia al repositorio y ejecuta npm install para instalar las dependencias requeridas. Una vez instalado, inicia el servidor de desarrollo local con npm start. Dentro de la carpeta de paquetes, encontrarás nuestra propia versión de React, que incluye los archivos clave que actualizaremos. El archivo index actúa como el punto de entrada donde manejaremos las funciones de React, como el estado, los efectos y la renderización.

Entonces, debería verse así. Primero, probablemente quieras decir que cambies al repositorio. Y quieres hacer una instalación de npm. Para instalar todas nuestras dependencias requeridas. Y una vez que estén instaladas, queremos ejecutar npm start. Lo cual inicia nuestro servidor de desarrollo local. Echemos un vistazo rápido a nuestra estructura de archivos. Tenemos la aplicación de tareas, que contiene nuestra aplicación de React. Realmente no necesitamos mirar eso. Pero lo que sí necesitamos revisar es la carpeta de paquetes, que contiene nuestra propia versión de React. Y estos son los archivos clave que luego actualizaremos. Y este archivo index actúa como nuestro punto de entrada. Y es donde reemplazaremos las funciones de React que queremos manejar. Como el estado, los efectos, nuestras funciones de renderizado y cosas así.

3. Renderizado de componentes y DOM

Short description:

Vamos a abordar el primer capítulo, que trata sobre el renderizado de componentes. Aprenderemos cómo renderizar JSX en nuestro DOM del navegador, con el objetivo de tener nuestra aplicación renderizada estáticamente. El modelo de objetos del documento (DOM) es la estructura de árbol que representa el HTML que se está renderizando. Los elementos de React son similares a los elementos del DOM, pero se representan como objetos. Comenzaremos deteniendo el servidor y cambiando la configuración de webpack. Luego revisaremos el Capítulo 1, Paso 1, y repasaremos los cambios realizados en la aplicación Todo. Utilizaremos DOMHangers como el equivalente de React DOM y nuestro propio React. Renderizaremos nuestro primer elemento utilizando create root y el método render. Luego pasaremos a DOMHanders y seguiremos los comentarios de `start here` y `don't forget`. El paso actual y la información útil se pueden encontrar en el snack box. La luz de estado indicará nuestro progreso. La recarga de modelo en caliente no forma parte de este trabajo.

Entonces, ahora voy a pasarle la palabra a Jean, y vamos a abordar el primer capítulo, que trata sobre el renderizado de componentes. Genial. Entonces, voy a... Creo que, Jean, debes dejar de compartir tu pantalla para que yo pueda compartir la mía. Afortunadamente. Muchas gracias. Genial. Así que también compartiré mi pantalla. Y echaremos un vistazo al primer capítulo, que trata todo sobre el renderizado. Y la idea es que a través de este capítulo, aprenderemos cómo renderizar JSX en nuestro DOM del navegador, y al finalizar, esperamos tener nuestra aplicación renderizada estáticamente. Y hay algunos conceptos que podrían ser útiles, ya que los usaremos bastante. Así que DOM significa modelo de objetos del documento. Y es una especie de estructura de árbol que el navegador utiliza para representar el HTML que se está renderizando en ese momento. Y más adelante utilizaremos un concepto similar con el DOM visual en memoria. Más sobre eso más adelante. Y tal vez un punto que es un poco diferente entre JSX y cómo se ve el DOM es que los elementos de React. Entonces, la mayoría de ellos son como elementos del DOM, pero se representan como objetos. Pero algunos de ellos también son un poco más complicados, como los componentes, que son funciones. Pero lo veremos a medida que avancemos en este capítulo. Aquí, comenzaremos deteniendo el servidor en caso de que lo tuvieras en ejecución, porque cambiaremos la configuración de webpack. Así que necesitamos reiniciarlo. Y luego podemos revisar el Capítulo 1, Paso 1, para comenzar. Y después de hacer eso, podemos volver a iniciar nuestro servidor para que tome la nueva configuración de webpack. Y como primer paso, tal vez te guíe a través de lo que está sucediendo aquí. Entonces, hay dos pequeñas cosas que hicimos entre la versión anterior y esta versión de la aplicación Todo. Una es que dentro de webpack, hicimos referencia a React como mi propio React. Entonces, cada vez que importes algo de React, en realidad importará de mi propio React. Y la segunda parte es que en el archivo index, cambiamos un poco lo que se renderiza aquí en lugar de nuestra aplicación. Así que creamos estos DOMHangers que serán el equivalente a React DOM y nuestro propio React. Y estamos haciendo algo bastante similar a lo que haríamos con React, ¿verdad? Estamos utilizando create root de nuestros DOMHanders con el elemento raíz en el que queremos renderizar nuestro primer elemento. Y luego llamamos al método render, que se expone con lo que queremos renderizar. Y pongamos aquí un div primero. Y para este primer paso, te guiaré a través de él. Y el siguiente paso es ir a nuestros DOMHanders. Y cuando sigas los diferentes pasos, siempre encontrarás dentro del código un comentario que dice `start here` como este. Así que puedes buscarlos y eso te indica dónde empezar. Y también hay algunos comentarios que se llaman `don't forget`, como este. Así que puedes buscarlos para el siguiente paso después de terminar el `start here`, en caso de que haya varios lugares donde necesites modificar el código. Ahora, para el primer capítulo, no es muy evidente, pero tienes que hacerlo, así que agregamos algunas pequeñas indicaciones que puedes ver aquí. Entonces, en este caso, te está diciendo que por ahora no parece que estés renderizando nada. Y debes ir a mis propios DOMHandlers de React para comenzar. Y aquí tienes una pequeña caja de snack que te dice un poco de qué se trata este paso actual y qué estamos tratando de hacer, y alguna información útil. Y para el primer capítulo, también tienes una pequeña luz de estado aquí. Comienza en rojo cuando comienzas porque aún no hemos completado este paso. Y en algún paso, puede volverse naranja a medida que comienzas a tener algo funcionando. Pero tal vez no todo esté funcionando y debería estar en verde al final una vez que todo esté funcionando. Dos pequeños puntos adicionales. La recarga de modelo en caliente está rota. No forma parte de este trabajo arreglarlo.

4. Renderizado de JSX y elementos del DOM

Short description:

JSX es un pequeño lenguaje de plantillas que nos permite escribir cosas de manera similar a como escribiríamos HTML, pero también incluye JavaScript dentro de él. Podemos crear un elemento HTML basado en el tipo del hijo raíz e insertarlo en el elemento raíz. Después del primer capítulo, nuestra aplicación comenzará a funcionar, lo que facilitará obtener comentarios sobre cómo completar los pasos correctamente. El siguiente paso es pensar en los atributos y props.

Entonces, cuando veas estos mensajes, puedes ignorarlos. Lo mismo con este. Y creo que esto también es solo un problema de falta de manifiesto. Podemos ignorarlo. Así que siempre verás estos errores, pero podemos fingir que no están aquí.

Volviendo a nuestros manejadores del DOM donde deberíamos comenzar. Y ahora que estamos aquí, estamos pensando en renderizar nuestro elemento JSX, que es este, que es un div. Y eso nos dice que deberíamos aprender un poco más sobre JSX. Así que hagámoslo. Y abramos esto en la vista previa.

JSX es un pequeño lenguaje de plantillas que nos permite escribir cosas de manera similar a como escribiríamos HTML, pero también incluye JavaScript dentro de él. Y en su forma más simple, realmente se parece a HTML. Así que esto es casi un HTML válido, y eso representaría el div, excepto que podemos cerrarlo automáticamente, lo cual sería inválido en HTML. Y esto se transforma mediante la configuración web de Create React App en un objeto. Entonces, lo que trataremos dentro de nuestro código es un objeto del cual, por ahora, lo único que realmente nos interesa es la propiedad de tipo. Y dentro de ella, será un div como una cadena. Y si intentamos con un tipo diferente, digamos, span, entonces obtendríamos span como una cadena. Así que eso suena lo suficientemente bien para el paso en el que estamos. Y volveré a nuestros manejadores del DOM. Y solo confirmaré lo que acabo de decirte. Entonces, si registramos en la consola nuestro canal raíz y guardamos eso, y no hay recarga en caliente, así que siempre actualiza después de hacer la modificación. Y podemos ver que registramos este objeto. Si ignoramos algunas de las cosas más extrañas por ahora, podemos ver nuestro tipo div. Así que eso no suena tan mal. Y lo que podríamos hacer entonces, sabemos que el nombre de etiqueta de este hijo raíz sería el tipo. Y podemos crear un elemento HTML haciendo document.createElement y pasando el nombre de la etiqueta. Entonces, normalmente ese debería ser nuestro elemento HTML. Y luego deberíamos poder usar nuestro elemento raíz, que es el elemento en el que queremos insertar nuestro react y agregar el hijo de nuestro elemento. Y si todo salió bien, deberíamos estar creando un elemento basado en el tipo de este hijo raíz. Luego, este elemento HTML lo insertaríamos en el elemento raíz. Entonces, en teoría, eso debería estar bien. Intentemos actualizar. Muy bien, el mensaje extraño y grande en el medio desapareció. Tenemos una luz naranja aquí arriba que nos dice, genial, puedes renderizar un div. ¿Qué pasa si intentamos renderizar algo más? En teoría, también deberíamos poder renderizar un span. Así que intentemos poner un span aquí. Y guardemos eso. Actualizar. Estamos en verde. Y si miramos en nuestro DOM y abrimos nuestro elemento raíz aquí, entonces podemos ver que tenemos el span renderizado aquí. Así que eso es prácticamente nuestro primer paso que hicimos juntos. Y el siguiente paso durante el primer capítulo se verá similar a este en términos de lo que puedes ver con el estado de la luz, y así sucesivamente. Y después del primer capítulo, nuestra aplicación comenzará a funcionar. Por lo tanto, será un poco más fácil obtener comentarios adecuados sobre si estás completando los pasos correctamente o no. Y luego revisaré la siguiente rama. Así que puedo prepararte para tu primer intento de hacer esto. Y haré un pull por si acaso, ya que no estoy seguro de si tengo las últimas cosas. Todo está bien. Genial. Entonces, el siguiente paso que vamos a tomar es pensar en los atributos y props.

5. Entendiendo Props y Manejo de Atributos

Short description:

Los props son similares a los atributos HTML y se utilizan para hacer que los elementos sean más útiles al agregar metadatos adicionales. En JSX, los props se representan como un objeto con pares clave-valor. A veces, los props no coinciden exactamente con los atributos, como usar className en lugar de class. En algunos casos, la capitalización es diferente, como usar camelCase en lugar de kebab-case. Los manejadores del DOM manejan los props y llenan los atributos correctamente. Utilizamos una función de utilidad para aplicar los props al elemento HTML. Para los event listeners, hay un código adicional para manejarlos.

Entonces, ¿qué son los props? Los props son un poco similares a los atributos HTML. Si miras aquí en HTML, tenemos un atributo ID que tiene el valor test. Y eso nos ayuda a hacer que los elementos sean más útiles y agrega metadatos adicionales a veces a los elementos. Y es un concepto bastante importante en HTML. Y funciona de manera bastante similar en JSX.

También podemos usar un ID. También podemos ponerlo a prueba. Y en este caso, esperaríamos que los props se conviertan en el HTML final. Y dentro de nuestro JSX, este JSX siguiente se convertiría en un objeto que se ve así. Todavía tenemos nuestro tipo d, pero ahora estamos viendo una propiedad adicional del objeto JSX, que es la propiedad props. Y este es un objeto que tiene cada prop como un par clave-valor. El ID se convirtió en la clave de este prop, y el valor test está aquí arriba. Y si tenemos más props, entonces simplemente obtenemos un objeto más grande con cada par clave-valor agregado. Y hay una consideración adicional a la que debes prestar atención.

Recomendamos que comiences con el ID. Eso probablemente sea uno de los más simples. Pero en algunos casos, los props no coinciden exactamente con los atributos. ClassName es uno famoso, donde tenemos que usar className, porque class es una palabra reservada en JavaScript. Entonces no fue posible simplemente llamar al prop class. Y en algunos casos, la capitalización es un poco diferente. Por ejemplo, acceptCharSet está en kebab-case. Pero en JavaScript en general, preferimos camelCase, lo que llevó a un problema potencial para los desarrolladores de GSE. Y decidieron usar camel casing aquí. Entonces, en algunos casos, también debes ver qué sucede cuando ocurre la diferencia de capitalización. Y eso es prácticamente todo.

Y cuando llegas a los manejadores del DOM, aquí tenemos prácticamente lo que hemos visto, pero un poco más organizado. Tenemos esta función, renderTagElementToHTML. Recibe nuestro hijo raíz JSX, y esta cosa recibe props y tipo. Con el tipo, creamos nuestro elemento que sucederá más adelante. Y aquí ahora, necesitamos manejar los props para que los atributos se llenen correctamente. Entonces, lo que haré es revisar la siguiente rama, capítulo uno, paso tres. Y te explicaré un poco cómo manejamos estos cambios. Y te prepararé para el siguiente paso. Entonces, estábamos en algún lugar por aquí, ¿verdad? Y hasta ahora, teníamos nuestro renderTagElementToHTML aquí. Y nos preocupábamos principalmente por los props, ¿verdad? Todavía no teníamos hijos, eso viene después. Y el tipo, y estábamos creando nuestro elemento del DOM para el tipo y devolviéndolo aquí. Y ahora se te pidió que revisaras los props por objeto de entradas y extrajeras la clave y el valor. Y luego, con el fin de facilitar un poco el código para recorrerlos, creamos esta función de utilidad applyProp toHTMLElement que toma nuestra clave valor y un elemento del DOM al que queremos aplicarlos. Y si miramos aquí arriba, lo mismo, ¿verdad? Obtenemos clave valor que son atributos y nuestro elemento. Una cosa que no revelamos porque agrega un poco más de complejidad para manejar los event listeners. Necesitamos un poco de código adicional, por lo que no tuviste que hacer eso pero tenemos que hacerlo más adelante en el taller. La parte que se te pidió hacer está aquí y lo hicimos de una manera interesante y te explicaré un poco qué significa esto. Creo que probablemente llegaste a este o a este, que esencialmente, ¿verdad? coloca en nuestro elemento para el atributo clave un valor específico. Cuando comenzamos con el taller, solo teníamos setAttribute y eso funciona para la mayoría de los casos pero aquí la clave debe ser la clave CSS. Por ejemplo, no puedes poner className aquí y tiene una cosa extra extraña que si el, estás tratando de establecer el valor para un input y la clave es el valor del input y el valor es una cadena vacía, de alguna manera eso en realidad no funciona y eso no restablece el input para que esté vacío mientras que esto sí lo hace. Entonces, reemplazamos esto con esto pero por ejemplo, para aria-hidden, eso no funciona porque esta clave aquí se espera que sea el estilo JavaScript y no el estilo Ja6, ¿verdad? Entonces no puedes tener el guión aquí. Debería ser aria-hidden con una H mayúscula. Entonces, lo que hicimos fue verificar si esto es indefinido dentro del DOM y cuando esta cosa no está establecida pero es una clave válida para este elemento entonces esto sería null, no indefinido. Entonces, si esto es indefinido, estamos bastante seguros de que esta clave no es una clave válida CSS de JavaScript. pero debería ser la clave válida regular CSS. Entonces, por defecto, usamos setAttribute para aquellos y para el resto de ellos, podemos establecerlos así. Y la última pequeña cosa es para los event listeners.

6. Manejo de Event Listeners, Children y Componentes

Short description:

Agregamos event listeners, como onClick para eventos de clic y onChange para eventos de entrada. Los children son los elementos que renderizamos dentro de un elemento específico. El manejo de children y valores primitivos implica mapearlos y aplicar lógica de renderizado específica. El elemento principal de renderizado alterna entre renderizar primitivas y stacks. A continuación, pasamos al capítulo uno, paso cuatro, donde manejamos los children y los agregamos al DOM. Los componentes son una parte emocionante de nuestro viaje con JSX, comenzando con componentes funcionales como el componente de título principal.

Entonces, tenemos que agregar un event listener de esta manera y lo que hicimos es crear un pequeño mapa de los event listeners en los que estamos interesados para el taller y la mayoría de ellos, ¿verdad? Se transfieren bastante fácilmente a sus eventos reales. Entonces, onClick es un evento de clic. El único extraño aquí es onChange que técnicamente se establece por defecto en input por React para que cuando cambies, la diferencia es que change debe tener un evento de desenfoque para activarse mientras que input se activa en cada entrada de tecla por lo que es un poco más eficiente.

Genial, nuestro próximo paso será sobre los children como puedes ver aquí, pero antes de entrar en el código tal vez continuemos un poco en nuestra pequeña documentación de JSX que tenemos aquí. Entonces, ¿qué son los children? Los children son simplemente los elementos, ¿verdad? Que estamos tratando de renderizar dentro de un elemento específico. Entonces, en este caso, nuestro d con ID root tiene dos children. El primero es un span que dice el primer child y el segundo es otro span que dice un segundo child. Y en JSX, se ve exactamente igual, ¿verdad? Como este es un JSX válido que también es un HTML válido en este caso y es la misma idea. El primer child está aquí, el segundo child está aquí. Nuestra estructura, sin embargo, se vuelve un poco más complicada, ¿verdad? Cuando comenzamos a tener todo esto, entonces podemos imaginar que el objeto JSX de nivel superior que tendremos es un tipo div y este div tiene dos children y children es un array en este caso. Y el primer children también es un elemento JSX, que es un span, y solo tiene un child. Y es un poco extraño, pero cuando JSX tiene children que es un solo child, en lugar de ser un array, es directamente la cosa que quieres renderizar. Entonces, en este caso, es solo un string porque es la cadena final dentro de este componente, este elemento, lo siento. Y el segundo children se ve casi igual, es nuevamente un span, también tiene children, que nuevamente es solo un child, que es directamente el string y dice un segundo child. Si profundizamos un poco en cómo queremos manejar eso, como puedes ver en nuestro renderTagElement ahora estamos extrayendo los children. Y aquí decimos que si hay algo en los children, entonces tendremos que hacer algo. Pero también agregamos un poco de código para manejar valores primitivos, que aún no hemos visto. Entonces, los valores primitivos en nuestro ejemplo aquí, serían las dos cadenas que están aquí, que no son realmente HTML válido en absoluto, y tampoco tienen un tipo como los demás. Entonces decidimos manejarlos por separado. Y lo que hacemos para ellos es cambiar según su tipo, y para cadenas y números los renderizamos como texnode con el valor dentro de él. Para undefined no renderizamos nada, solo undefined. Y para los booleanos, si es true, entonces es true en realidad, ¿verdad? Es un booleano, por lo que tiene que ser true o false. Si es true, lo renderizamos como una cadena, como si fuera un error. Pero si es false, probablemente sea un renderizado condicional que se pretendía. Entonces, poner undefined aquí es bueno porque entonces no renderizaremos nada. Y ahora tu tarea es pensar en cómo manejar los children, ¿verdad? Entonces tendrás que pensar un poco sobre cómo funciona esto. Ah, y lo último, este elemento principal de renderizado ahora simplemente cambia. Si es un elemento primitivo, lo renderiza como un elemento primitivo. Y si no, lo renderiza como un stack. Entonces deberías poder usar eso también dentro de tu solución para que todo funcione. Vamos a revisar la siguiente rama. Está bien, que será el capítulo uno, paso cuatro. Paso cuatro. Y solo por si acaso nos moveremos. Y te guiaré a través de los cambios que hicimos y también de los próximos pasos que estamos preparando para ti. Entonces, estábamos aquí, ¿verdad? Y estábamos viendo cómo manejar nuestros children. Y la pequeña parte que no está aquí, pero te guiaré a través de ella después. Pero en caso de que tengamos children, lo que hacemos desde aquí es mapearlos. Y para cada uno de ellos, vamos a llamar a nuestra función render element to HTML, que es aquella que toma primitivas o elementos de etiqueta y los transforma en algo que podemos renderizar en el DOM. Y una vez que los tenemos como elementos del DOM, podemos recorrerlos nuevamente. Y verificamos si realmente tenemos algo o no. En algunos casos, devolvemos un define para renderizado condicional o para undefined. Entonces no queremos intentar abrir eso, pero para todo lo demás, podemos agregar el child al DOM. Y luego, al final, ¿verdad? Todo esto se agregará al elemento root. Entonces, si todo salió bien, y actualizo aquí, espera un segundo, creo que necesitaría volver a poner lo que se suponía que debíamos tener aquí antes, que sería algo con children, ¿verdad? Entonces digamos simple test. Y eso se renderizaría aquí. Así que suena bien. Y ahora el siguiente paso en nuestro viaje con GSX, que podría ser el más emocionante, son los componentes. Entonces, primero podemos ver cómo se ve un componente. Y en React moderno, probablemente sea un componente funcional que se ve algo así. Entonces, este es un componente de título principal.

7. Renderizado de Componentes y VDom

Short description:

Creamos el componente de título principal, que recibe una prop de título y renderiza un elemento H1 con la clase 'main title' y el título como contenido. Manejamos los componentes por separado de los elementos del DOM y usamos la función GetRenderableVDom para renderizarlos. La función de renderizado maneja primitivas y componentes de manera diferente, mapeando los children y renderizándolos según corresponda. El VDom representa el árbol actual en React, lo que nos permite almacenarlo en memoria y rastrear cambios. Podemos identificar elementos basados en su posición en el árbol usando el índice dentro del array de children. Los componentes son importantes para el VDom pero no se renderizan en el DOM final del navegador. Podemos representar la estructura de JSX en una estructura similar a un árbol y usarla para identificar elementos dentro del VDom.

Como prop, recibe un título y quiere renderizar un H1 con la clase 'main title'. Dentro del H1 estará el título. Lo usaríamos de esta manera en GSX, ¿verdad? Así que crearemos el componente de título principal y le daremos la cadena como título. Y una vez transformado en JavaScript, se verá algo como esto, donde el tipo ahora es la función de título principal que hemos definido aquí. Y dentro de las props, igual que antes, ¿verdad? Recibimos nuestras props de la manera normal. Y ahora tenemos que pensar un poco en lo que significa cuando recibimos una función aquí y cómo podemos manejar eso. Y hemos empezado a adentrarnos un poco más en la arquitectura de cómo hacemos las cosas.

Entonces, lo que ya hemos hecho es crear aquí esta función GetRenderableVDom que proviene del índice y aquí la estamos llamando. Y lo que obtenemos aquí básicamente será, la idea es que los componentes no son realmente algo que sepamos cómo renderizar dentro del DOM. Por lo que no son muy importantes para los controladores del DOM, pero para nuestra función de React, a largo plazo, son bastante importantes porque necesitamos saber cómo renderizarlos. Por lo tanto, decidimos que dentro de este archivo solo tendríamos cosas que sepamos cómo manejar dentro del DOM. Y por otro lado, podemos manejar cosas que son más específicas de React, como los componentes. Y vayamos a nuestro otro índice, a nuestro índice, lo siento, no otro índice, ese es el único índice. Y así tenemos nuestra función GetRenderableVDom, que está aquí, y estamos hablando de VDom aquí, y lo presentaré en un segundo. Pero primero, creo que podemos ver cómo funciona nuestro render. Entonces, el renderizador funciona de manera bastante similar al otro lado, ¿verdad? Tenemos una función similar aquí que maneja primitivas y otros componentes de manera diferente. Y para las primitivas, no hace mucho. Básicamente, solo devuelve las primitivas porque no tenemos que hacer nada con ellas. Y para nuestros elementos de componente, extrae los children y las props, y en caso de que tengamos children, hay un paso adicional aquí para verificar si los children son un array o no, y si no son un array, por conveniencia, los transforma en un array, y luego los mapea y también los renderiza, y luego devuelve los children como resultado de renderizarlos dentro de este archivo. Y luego aquí es donde tendremos que manejar los componentes, por lo que en caso de que nuestro tipo sea una función, eso significa que estamos tratando de renderizar un componente funcional. Entonces, colocamos el tipo en este componente funcional, y aquí ahora tendremos que renderizarlo realmente, y hemos hablado bastante sobre el vdum. Así que hablemos sobre el vdum. La idea del vdum es tener una representación del árbol actual que tenemos en React de una manera que podamos almacenarlo en memoria y tener fácil acceso a diferentes componentes dentro de él. Y la razón, o algunas de las razones por las que querríamos eso, una de ellas es más adelante cuando intentemos introducir los hooks, entonces tendremos que saber a qué componente pertenece un hook. Por lo tanto, tendremos que tener algún tipo de representación vertical y con el tiempo, a medida que volvamos a renderizar, necesitaremos saber, ya sabes, como el estado anterior de este componente era esto. Entonces, cuando volvamos a renderizar, tendremos que tener el estado nuevamente. Y una vez que también entremos en la diferenciación y las actualizaciones dirigidas, en ese momento también tendrá la importancia similar donde podemos comparar el actual con el anterior para poder entender qué ha cambiado con el tiempo. Entonces, pensemos un poco en cómo puede verse eso. Si imaginamos una página HTML, algo así, donde tenemos un div principal que contiene como primer hijo otro div, luego este div contiene como hijo un span y esto dice, ¡hola mundo! Y el div principal, el div raíz, también contiene otro hijo, que dice otro span. Y tratamos de pensar en cómo podemos identificar todos esos y la forma en que React realmente lo hace se basa en dónde están dentro del árbol, ¿verdad? Entonces, todo se basa en su posición en el árbol. Entonces, una forma en que podemos representar esta estructura en una estructura similar a un árbol podría ser algo como esto. Tenemos nuestro div superior, tiene dos hijos, y el primer hijo también podría tener el ID cero. Eso es el children en el índice cero, y este podría tener el ID uno. Eso es el children en el ID uno, y luego hacemos lo mismo a medida que bajamos, pero simplemente agregamos al puntero ya existente a medida que avanzamos. Entonces, este es el primer hijo de este div, y como también es un hijo de este div, comenzará con cero para identificar este div, luego una coma, y luego dentro de este div, es el primer hijo, y este es el primer hijo de este. Por lo que hereda básicamente toda la estructura que fue antes que él y luego agrega una coma cero, y en el otro lado, este es el segundo hijo. Por lo tanto, ese es el índice uno y su hijo sería uno coma cero porque ese es el índice cero dentro de este. Bien. Eso no es todo. Sí, está bien. Y lo siguiente en lo que debemos pensar, ¿verdad?, en lo que ya comenzamos a hablar es que algunas cosas en realidad no se están renderizando en el DOM final del navegador, pero solo son importantes para nuestro vDOM, y la mayoría de esto son componentes. Entonces, si ahora imaginamos este JSX, tiene un div, un h1, luego una sección y luego un componente aquí. Pero esto no sería válido en HTML, ¿verdad? Solo funciona en JSX / React. Pero aún así, continuemos con este ejemplo. Y supongamos que nuestro contador se ve algo como esto. Es un componente que tiene un estado, comienza en cero, que es un contador, y luego renderiza un div, un span que dice el contador es el contador que está aquí, y un botón que simplemente incrementa el contador si haces clic en él, que tiene un signo más como texto. Entonces, sabiendo esto, podemos suponer que para la primera renderización, esta será la estructura que tenemos al final en HTML dentro del navegador. Y en este caso, ¿verdad?, el contador ya no está aquí, sino que ha sido reemplazado por nuestro div, que es renderizado por nuestro contador. Cuando hablamos del vDOM renderizable, estamos imaginando esto, ¿verdad? Como sin componentes.

8. Comprendiendo la Estructura del VDOM

Short description:

Y cuando hablamos del VDOM, imaginamos una estructura que representa el DOM virtual. Nuestro elemento .div es similar al elemento GSX, pero con un puntero VDOM añadido. Los hijos renderizados son el resultado de renderizar componentes o transformar hijos, con punteros VDOM añadidos. Las primitivas se manejan de manera diferente, con un tipo de primitiva y su valor como su valor. Las secciones y los contadores son ejemplos de hijos renderizados, cada uno con sus propios punteros VDOM.

Y cuando hablamos del VDOM, estamos imaginando esto, pero esto también contiene hijos que deben ser renderizados más tarde. Ahora, este es un gráfico un poco confuso, acerquémonos un poco. Y está tratando de representar la forma en que imaginamos el DOM virtual. Probablemente habría mil formas de imaginar esto, pero la forma en que decidimos hacerlo fue tratar de mantenernos un poco en la estructura que tenemos, pero manejar los hijos y los componentes de manera un poco diferente. Entonces, la forma en que funciona es que nuestro elemento .div es similar a, lo siento, tiene dos elementos, todos ellos. Y el primero es el elemento que es bastante similar al elemento GSX con el que hemos trabajado hasta ahora, pero hemos agregado este puntero VDOM, que es uno de los punteros que vimos antes, ¿verdad? Apunta a dónde está dentro de nuestro VDOM. Y la segunda parte serán los hijos renderizados, que básicamente es el resultado, por ejemplo, de renderizar el componente o recorrer los hijos y transformarlos y también agregarles el puntero VDOM a todos ellos. Y si pensamos en el ejemplo anterior, ¿verdad? El primero era un H1 aquí, con el puntero VDOM 0 y los hijos renderizados con solo un elemento. Y dentro de él, había otro, y ahora las primitivas las manejamos de manera un poco diferente. Las tendremos como tipo primitiva y su valor será su valor. Y también vienen con un puntero VDOM. Y esto no tiene hijos renderizados. Y en el otro lado de las cosas, ¿verdad? Tenemos nuestra sección, que tiene el puntero VDOM 1 y tiene solo un hijo renderizado. Y este hijo renderizado es nuestro contador, que es de tipo, la función contador tiene un puntero VDOM 1-0 y tiene 1 hijo renderizado y así sucesivamente, ¿verdad? A medida que avanzamos en el bucle, seguimos teniendo los mismos elementos donde los hijos renderizados son el resultado de intentar renderizarlos. Y el elemento es muy similar a nuestro elemento j6, solo ligeramente cambiado por practicidad. Ignoremos esto.

9. Comprendiendo los Punteros del VDOM y el VDOM Renderizable

Short description:

Si queremos señalar al botón, recorreríamos el árbol y llevaríamos un registro del índice. Usamos funciones auxiliares como get-v-dom-element y set-current-v-dom-element. Los hijos renderizados se manejan de manera diferente a props.children. El VDOM renderizable reemplaza el componente con el div que renderiza, pero los punteros del VDOM permanecen iguales.

Entonces, esto es un resumen de lo que acabamos de decir, ¿verdad? Si queremos señalar arriba al botón, recorreríamos el árbol y llevaríamos un registro del índice por el que pasamos. Primero tendríamos que seleccionar la sección, que está en el índice uno dentro de la raíz. Luego seleccionaríamos el contador, que está en el índice cero dentro de la sección, el div en el índice cero dentro del contador y el botón en el índice uno dentro del div. Esto nos llevaría a un array, algo como esto, 1001. Y usaremos esos punteros en todas partes para encontrar elementos en el DOM o establecerlos en nuestro DOM virtual. Creamos algunas funciones auxiliares para ayudar a hacer este tipo de cosas. Una es get-v-dom-element, y le das un puntero del VDOM y el VDOM actual y devolverá un elemento del VDOM. Otra es set-current-v-dom-element, toma un elemento puntero y el VDOM que tiene tanto el actual como el anterior. Y estableceremos este elemento en el VDOM anterior en el puntero que pasaste aquí. Y la última es crear este elemento del VDOM del que estamos hablando aquí y aquí, al que le das un elemento JSX más un puntero, y creará la estructura que se ve algo así con el puntero del VDOM también y el elemento encapsulado y los hijos renderizados. Así que, si imaginamos usar esos, podríamos intentar hacer get-v-dom-element de este puntero en nuestro VDOM anterior y eso debería devolver el botón con el ejemplo anterior. Y supongamos que queremos reemplazar el botón por un span. Nuestro puntero sería el mismo y crearíamos nuestro elemento del VDOM del componente con los hijos reemplazados y un nombre de clase como props. Y será un span y tendrá el puntero del VDOM que acabamos de establecer aquí. Y luego lo estableceríamos de esta manera para reemplazarlo. Y la última parte que puede ser un poco extraña es sobre los hijos renderizados, ¿verdad? ¿Por qué no usar props.children? La idea aquí era que no queríamos mutar los props.children en el VDOM que mantenemos en caso de que más adelante cuando estemos definiendo queramos tener los props originales. Y tal vez la última parte entre el VDOM renderizable y el VDOM con todos los componentes. Esto es cómo se vería el VDOM renderizable para el ejemplo anterior. Y como puedes ver, la única diferencia es que el componente ya no está aquí. En su lugar, se reemplaza directamente por el div que renderiza, pero los punteros del VDOM siguen representando la estructura de los componentes que tenemos. Entonces, mientras que este es el puntero del VDOM uno, esto es uno, cero, cero porque antes de llegar al renderizable, había un componente aquí.

10. Renderización de Componentes y Gestión de Estado

Short description:

Ya hemos configurado las diferentes funciones auxiliares dentro de esta función para que no tengas que hacer mucho. Tu tarea principal aquí es pensar nuevamente en este componente funcional y cómo renderizarlo. Estábamos dentro de nuestro índice y estábamos viendo nuestro componente funcional. Teníamos que llamar a este componente funcional con sus props y renderizarlo en elementos listos para ser renderizados dentro del DOM. Ahora comenzamos con el capítulo dos, que se centra en el estado. El estado nos permite almacenar datos dentro de nuestros componentes. React ha introducido hooks, y uno de estos hooks se llama useState. Te permite establecer el estado dentro de tu componente funcional. La función useState toma el estado inicial como argumento y devuelve un array que contiene el estado y una función de actualización. En nuestra aplicación, ahora estamos renderizando componentes, pero necesitamos actualizar el estado para ver cambios en la página. Nos centraremos en la función useState y en el uso de funciones de orden superior.

De acuerdo, eso fue mucho. Normalmente no tienes que lidiar demasiado con el VDOM por ahora. Ya hemos configurado las diferentes funciones auxiliares dentro de esta función para que no tengas que hacer mucho. Tu tarea principal aquí es pensar nuevamente en este componente funcional y cómo renderizarlo. Básicamente, cómo transformar esta función que debería devolver JSX en JSX real que pueda ser renderizado por el DOM. Y tal vez lo último mientras lo haces, ¿verdad? Por ahora, intenta simplemente renderizar esta prueba simple que está aquí. Si logras hacer esto, luego puedes intentar renderizar una prueba simple con props donde tendrías que manejar props. Y luego puedes intentar renderizar una prueba mega que básicamente usa la prueba simple con props para asegurarte de que todo funcione dentro de tu solución.

Estamos en un horario ajustado, desafortunadamente. Así que pasaré al siguiente paso y te guiaré a través de lo que hicimos. Y después de eso, tendremos un pequeño descanso para poder digerir un poco lo que acabo de explicar. Eso ya es bastante. Genial. Estábamos dentro de nuestro índice aquí y estábamos viendo nuestro componente funcional, pero ignoraré la parte de los hooks. Y lo que teníamos que hacer era llamar a este componente funcional con sus props aquí. Y luego podemos renderizar eso en elementos listos para ser renderizados dentro del DOM y simplemente devolver eso. Normalmente, una vez que esto funciona, si miramos aquí, estamos renderizando nuestra aplicación. Y si actualizo la aplicación en mi navegador, entonces tenemos una primera versión de la aplicación funcionando. Es completamente estática, ¿verdad? Nada sucede si haces algo. Ese es nuestro próximo paso. Pero ya es bastante genial ver que tenemos JSX funcionando junto con componentes y que los hijos de los hijos de los componentes también se manejan correctamente.

Parece que algunos de ustedes, desafortunadamente, están experimentando algunas dificultades de sonido. Sí, disculpen por eso. Y también, sí, no probamos en otras versiones de Node. Y así, la versión de Node 16 es la versión que necesitas. Sí, eso fue un error nuestro, tuvimos una omisión por nuestra parte para aquellos que aún tienen problemas con eso. Y también, si ejecutas git fetch desde donde estés, ahora deberías tener acceso a la documentación de Vdom cuando cambies de rama. Tampoco la hemos subido, si haces pequeñas cosas allí. Pero ahora comencemos con el capítulo dos, que se centra en el estado. ¿Y qué es el estado? Nos vamos a centrar en el estado local, similar a las props o los datos que se proporcionan a un componente, pero el estado es privado y está completamente controlado por ese componente. Y permite que nuestras aplicaciones sean dinámicas. Y esencialmente nos permite almacenar datos dentro de nuestros componentes. Y antes de que React se moviera hacia el paradigma de la programación funcional, ahora se ha movido hacia... Tenías que usar componentes de clase para establecer el estado, pero sí, ahora React ha agregado hooks. Y un hook es simplemente una función de JavaScript que te permite encapsular código en ella. Y uno de estos hooks se llama useState. Y esto te permite establecer el estado dentro de tu componente funcional, por lo que es realmente útil. Y en el lado derecho, puedes ver cómo se ve esto. Como dije, un hook es una función, por lo que useState es una función y toma un argumento que es el estado inicial. Entonces, por ejemplo, en este contador, es cero y luego devuelve un array que contiene dos valores. El primero es el estado actual y los datos en los que estamos interesados, y la segunda es la función setCount que usamos para actualizar nuestro estado. En resumen, es una función que toma un valor y devuelve un array que contiene el estado y la función de actualización. Si vamos a nuestra aplicación, puedes ver en esta etapa, así que deberías estar en la rama capítulo dos, paso uno. Ahora puedes ver que estamos renderizando componentes, lo cual es genial. Nuestra aplicación se parece más a una aplicación. Pero si hacemos clic en nuestro contador, por ejemplo, no sucede nada y eso se debe a que en realidad necesitamos actualizar el estado para ver lo que hay en la página. Así que vayamos a nuestro código. Una cosa clave aquí es en lo que nos vamos a centrar en términos del desafío es la función useState en sí, pero hemos tenido que agregar mucho para que el estado funcione y se actualice en cada renderizado, por ejemplo, y una idea clave es el uso de funciones de orden superior. Y eso es una función que devuelve una función.

11. Inicialización de Funciones y Funciones de Orden Superior

Short description:

La función createRoot en nuestros controladores de dom se utiliza para inicializar una función que se puede llamar más adelante. El método render se llama una vez cuando renderizamos por primera vez nuestra aplicación. También hemos agregado una nueva función llamada start render subscription, que es un ejemplo de una función de orden superior.

Y esto ha sido súper útil para nuestra implementación porque nos permite inicializar una función y luego llamar a esa función que se devuelve de la función más adelante, como cuando actualizamos una función, actualizamos la aplicación o en re-renderizaciones. Así que comencemos en nuestros controladores de dom. Tenemos esta createRoot, que ya hemos visto, y la createRoot tiene una función en ella. Hay un método render que se llama una vez cuando renderizamos por primera vez nuestra aplicación. Toma el elemento secundario de la ruta, que es la aplicación react, que reacciona a los usuarios para saber qué renderizar dentro de la aplicación. Aquí hemos agregado una nueva función, start render subscription, que es un ejemplo de una de estas funciones de orden superior.

12. Inicialización de Hooks y Manejo de Cambios de Estado

Short description:

En la renderización, nos suscribimos a los cambios del DOM impulsados por los cambios de estado. Instanciamos la función de suscripción de inicio de renderización para escuchar los cambios de estado y realizar actualizaciones. Si es la primera renderización, agregamos el hijo al elemento raíz. De lo contrario, reemplazamos el hijo. Creamos hooks para manejar los cambios de estado y pasamos la función de actualización a los hooks. La función create hooks inicializa hooks para cada componente utilizando un mapa de hooks referenciado por el puntero VDOM. Cada objeto hook contiene un campo de estado con información sobre el estado del componente. La función register hooks es una función de orden superior que crea hooks para cada componente en la renderización inicial.

Toma dos elementos, el hijo de la ruta, y luego otra función. Entonces, lo que esta función está haciendo es, en la renderización, nos permite suscribirnos a los cambios del DOM, que son impulsados por los cambios de estado. Entonces, instanciamos esto, ¿puede la gente escucharme?, acabo de ver algo sobre el uso del sonido. Sí, está bien, genial, continuaré. Sí, en nuestra primera renderización, estamos llamando a esto una suscripción de inicio de renderización, que nos permite suscribirnos y escuchar los cambios de estado para que podamos hacer actualizaciones. Y toma el hijo de la raíz y también una función, y esta es la función que llamaremos en nuestras actualizaciones, que toma el render all vDom, para que sepamos qué actualizar. Y aquí, si estamos mirando, si no hay último hijo, es prácticamente la primera renderización porque no existe nada. Entonces agregamos el hijo al elemento raíz. Si hay un último hijo, eso significa que ya tenemos elementos en nuestra página y usamos replace child en lugar de agregarlo. Entonces tenemos esta función aquí, esta es la cosa clave que persiste en toda la aplicación y es como nuestra función de actualización. Entonces, ¿dónde se llama esto? Si tuviéramos, ahora estamos en nuestro index.js o define, lo siento, quise decir, aquí es donde se define la función startRender subscription, y recuerda que toma ese elemento y luego ese segundo argumento era la función de actualización. Entonces, la función que maneja esa actualización del DOM. Entonces, nuestra función real aquí, aquí es donde almacenamos nuestro VDOM anterior, el DOM virtual y el actual. Y esto se llama una vez, recuerda que todo el código aquí, aquí es donde vamos a crear nuestros hooks para que la definición de qué son los hooks, recuerda que la función useState es un hook, es solo una función que contiene algún código. Pero aquí es donde lo inicializamos en esa primera renderización. Entonces necesitamos crear nuestros hooks. Para que nuestra aplicación sepa cómo manejarlos y lidiar con ellos. Y luego pasamos a la creación de los hooks, esta función de actualización aquí, que contiene nuestra devolución de llamada de actualización. Entonces, lo que está sucediendo aquí es que estamos pasando la función de actualización a nuestros hooks. Entonces, cuando nuestro estado cambia, por ejemplo, podemos llamar a la función de actualización y nuestro DOM puede volver a renderizarse de la manera correcta con la información correcta. Sí, esto es bastante complejo y estamos usando la función de orden superior por lo que es un poco difícil de seguir, pero sí, quería explicártelo para que al menos conozcas el trabajo detrás de escena. Entonces, veamos esta función create hooks, que es donde inicializamos nuestros hooks en esa primera renderización. Y tenemos un nuevo archivo que se ha agregado en esta rama hooks.js. Este es el archivo que manejará toda nuestra lógica de uso de estado. Y esta es la función que se llama en nuestra primera renderización. Toma la función de actualización. Recuerda, queremos saber cuándo cambia el estado, queremos llamar a las funciones de actualización para que podamos realizar cambios en nuestro DOM. Y aquí, lo importante es que estamos creando nuestro mapa de hooks. Ahora, este es un mapa, y contiene todos los hooks de nuestra aplicación, pero se referencia mediante el puntero VDOM. Entonces sabemos qué hook se relaciona con qué componente. Por ejemplo, el mapa de hooks con el siguiente puntero VDOM 0 0 0, es el hook para ese componente específico. Entonces podemos identificar y referenciar los hooks correctos. Y es importante saber que, por ejemplo, si llamara a esto, cada hook tiene la siguiente estructura. Entonces es un objeto que contiene un campo de estado, que es un array porque, cada componente puede tener múltiples estados y también afectaremos eso en el último capítulo de esto. Entonces, lo importante aquí es que nos estamos enfocando en tener un objeto hook para cada componente. Podemos acceder a ese hook usando el puntero VDOM, que es nuestra referencia. Y en ese hook, tenemos un campo de estado que contiene información sobre el estado de ese componente. Y otra cosa importante aquí, esto es como la inicialización de los hooks. Luego creamos cómo se ve esa lógica aquí. Y también estamos registrando los hooks. Esto es muy importante porque veamos qué función es. Es otra función de orden superior. Entonces lo llamamos una vez en nuestra renderización de clase. Le damos el mapa de hooks. Y le damos la función que crea nuestro useState. Y devuelve una función. Y luego esta función se llama para cada componente con el puntero VDON. Y si es la primera renderización. Entonces esto nos permite crear hooks para cada componente cuando los necesitamos. Y ¿cuándo es esto? Es importante tener en cuenta que esta función se llama en la renderización inicial. Y luego tenemos esta función register hooks.

13. Registrando Hooks y Manejando Renders

Short description:

Y luego eso también es una función que podemos llamar para componentes específicos. Entonces podemos crear hooks para ese componente. ¿Cuándo se llama a esta función de registro de hooks? Si vamos a... La barra de zoom se interpuso en mi camino. Entonces esa función de registro de hooks, que es responsable de manejar nuestros hooks, se registra en cada renderización.

Y luego eso también es una función que podemos llamar para componentes específicos. Entonces podemos crear hooks para ese componente. ¿Cuándo se llama a esta función de registro de hooks? Si vamos a... La barra de zoom se interpuso en mi camino. Entonces esa función de registro de hooks, que es responsable de manejar nuestros hooks, se registra en cada renderización. Entonces llamamos a la función de registro de hooks cuando estamos en nuestro método de renderización, este es nuestro elemento de componente de renderización. Entonces, cuando queremos renderizar un componente, que es la función de tipo, sabemos que necesitamos llamar a esas funciones de registro de hooks con el puntero de alimentación específico para ese componente. Y si es la primera renderización, eso reemplazará el hook existente que tenemos con uno nuevo y creará los hooks requeridos para esa función. Entonces, los datos no se vuelven obsoletos y se mantienen actualizados. Entonces, sí, esta es la función.

14. Creando la función useState y Manejando el Estado

Short description:

Esta es la parte clave: devolver la función que se llama cuando estás en tu aplicación y escribes useState. Espera un estado inicial, que puede ser nulo, y devuelve un array. El primer valor es el estado y el segundo es una función responsable de actualizar el estado. Necesitamos pensar en cómo almacenar el estado y configurar cada nuevo estado. Esta parte es específica de React y verifica si es una función para la Inicialización del Estado Perezosa. Necesitamos actualizar la función de establecer estado para hacer comparaciones con el estado anterior y el valor dado. También necesitamos actualizar nuestra aplicación y devolver tanto el estado como la función de actualización. La creación del useState asegura que los datos sean específicos para cada componente utilizando el mapa de hooks y el puntero VDOM. El valor actual del hook se inicializa y en la función useState podemos acceder al estado actual y actualizarlo. El estado es un array porque un componente puede tener múltiples estados.

Esta parte de esa función se llama así. Con el puntero VDOM es el primer renderizado. Y luego, cuando el componente se está renderizando, esto se llama, y luego es cuando queremos usar esa información para crear el useState específico para cada componente. Así que tenemos esta función make useState, y estamos pasando el puntero VDOM, que es la referencia al componente y es el primer renderizado. Y luego echemos un vistazo a esa parte, que es la parte en la que estamos específicamente interesados, que es la parte que se llama cuando estás en tu aplicación, estás en tu componente, y luego estás haciendo referencia a useState. Entonces. Aquí está. Aquí es donde está la lógica, y esto es lo que abordaremos primero. Así que esto es... Así que nuevamente, esta lógica de función de orden superior, donde esto se llama en el primer renderizado. Esta parte, esta función se activa. Se activa con la devolución de llamada onUpdate, que es importante porque luego esto necesita ser llamado en nuestro useState para actualizar el DOM. Entonces necesitamos actualizar lo que realmente se muestra en nuestra página. Esa es la función que se encarga de eso. Tenemos el mapa de hooks, para que podamos recuperar el hook específico que queremos y relacionarlo con el componente específico. Y luego tenemos la función, esta próxima función que se llama para cada componente y se le da el puntero VDOM y si es el primer renderizado. Entonces, utilizando todas las variables disponibles, podemos obtener el hook correcto o la lógica de estado correcta de nuestros hooks, podemos comparar los valores y luego podemos desencadenar actualizaciones de estado cuando hay cambios en los que estamos interesados y luego también actualizar nuestro DOM desde aquí. Entonces, ¿qué hace esta función? La parte clave es devolver esta función y esta es la función que se llama cuando estás en tu aplicación y escribes useState. Esto es lo que se devuelve y como dije al principio, ese useState espera un estado inicial, puede ser nulo, y devuelve un array. El primer valor es el estado y luego el segundo, que vamos a reemplazar es una función responsable de actualizar nuestro estado. Entonces, las cosas clave antes de que abordes esto es que necesitamos pensar en cómo queremos almacenar el estado para que aún podamos acceder a ese estado y hacer comparaciones cada vez que se llame a esa función. Entonces, ese es el primer paso de esta tarea. ¿Cómo almacenamos el estado y almacenamos un valor al que luego podemos hacer referencia? Y también necesitamos considerar la configuración de cada nuevo estado. Entonces, el hecho de que necesitamos devolver una función de actualización. Y solo queremos hacer eso en su primer renderizado, de ahí que este sea el bloque de primer renderizado porque solo queremos configurar la función de actualización una vez y luego podemos usar esa misma definición de la función a lo largo del ciclo de vida. Sí, esta parte es específica de React. La razón por la que estamos haciendo esto y verificando que sea una función es porque React te permite, tiene una función llamada Inicialización Perezosa del Estado y esto te permite pasar como valor de estado inicial una función y React luego ve, oh, has pasado una función. La voy a llamar una vez y solo una vez. Lo que permite, se llama Estado Perezoso porque te permite pasar o encapsular funciones altamente complejas que tienen un alto valor computacional como cuando estás usando el almacenamiento local para que solo se active una vez en el primer renderizado y no una y otra vez. Así que eso se tiene en cuenta. Pero eso ya está hecho por ti. Y luego necesitamos actualizar nuestro set state. Esta es nuestra función de datos que necesitará devolver. Y necesitamos manejar en esa función de actualización queremos hacer la comparación de nuestro estado anterior que ya hemos almacenado. Esa es nuestra primera tarea. Y luego estamos haciendo la comparación del estado anterior y el valor dado. Y luego también necesitamos actualizar nuestra aplicación. Recuerda lo que se nos da aquí en la parte superior. Y recuerda que necesitamos devolver tanto el estado como nuestra función de actualización. Y hay algunas pistas en el código. Si revisamos el capítulo dos, paso dos. Y luego veamos lo que hicimos. Entonces, y nos damos cuenta de que te estamos dando mucha información y te estamos pidiendo mucho. Creo que esta masterclass se podría hacer en una semana en lugar de tres horas, pero sí, gracias por tu paciencia. Lo más importante de esta creación del useState en esta primera parte es asegurarse de que los datos que establecemos sean específicos de ese componente. Queremos que ese hook esté vinculado a un componente específico. Y la forma en que lo hacemos es inicializar el valor actual del hook y utilizar este mapa de hooks que se pasa, que nuevamente es la colección de todos los hooks en nuestra aplicación, pero con la clave siendo la referencia al puntero VDOM que representa eso. Entonces, y podemos usar el puntero VDOM, que es el puntero específico para ese componente y así es como podemos almacenar y también recuperar el hook específico para cada componente. Entonces ahora tenemos nuestro hook actual. Y luego, cuando pasamos a nuestra función useState real, podemos acceder al estado actual y en este momento estamos tomando el primer valor del estado, recuerda que el estado es un array porque un componente puede tener múltiples estados.

15. Actualizando el Estado con Múltiples Estados por Componente

Short description:

Tomamos el primer valor y luego lo comparamos con el valor que se pasa, es decir, el nuevo valor del estado. Luego tomamos el estado anterior y el actual. Tenemos esta función auxiliar, stateStiffer, que simplemente hace una verificación simple en el estado anterior y el nuevo estado. Y luego, si se debe actualizar el estado, establecemos el valor del estado en nuestro hook. Entonces, el hook actual, currentHook, cambiamos ese valor para representar el nuevo estado. Y luego, lo importante, para reflejar los cambios en nuestra página, necesitamos llamar a nuestra función de actualización. Y esa es la función que recordamos que se pasa hasta el final y que realmente realiza los cambios en nuestros elementos del DOM. Y, por supuesto, aquí es donde hacemos los cambios finales en el estado inicial. Y también devolvemos la función de actualizaciones. Y luego, lo último es devolver ese estado desde la función useState. Veamos qué significa esto para la aplicación en este estado actual. Cometí el error de decir que el contador debería funcionar. El contador no debería funcionar en este punto, y veremos por qué. Pero, si agrego un elemento ahora, podemos ver que el elemento se agrega correctamente a la lista de tareas pendientes. Pero algo extraño ha sucedido en nuestro campo de contador. Está tomando el estado que establecimos para nuestra lista de tareas pendientes y también lo ha puesto en el estado de nuestro contador. Claramente, eso no es lo que queremos. Y eso se debe a que nuestra implementación actual solo tiene en cuenta que el componente puede tener un estado por componente. Entonces, si puedes ver, si vamos al código, está mostrando eso. Entonces, esto es esencialmente, si miras en este common, cómo se ve nuestro componente de la aplicación. Tiene el contador en el setCounter, y luego el mismo componente, también tiene, bueno, en la aplicación son los elementos de la lista de tareas pendientes. Entonces, los elementos. Entonces, nuestro componente tiene dos estados, pero solo estamos actualizando un estado y asumiendo que el componente solo puede tener un estado. Estos dos estados están compartiendo el mismo estado en este momento. Entonces, lo que necesitamos hacer ahora es permitir que nuestra nueva función de estado maneje múltiples estados por componente. Para que cada tipo de estado se actualice con el valor correcto. Y algo importante a tener en cuenta es cómo React maneja esto, lo maneja secuencialmente, por índice. Entonces, este es el primer índice que tenemos, el índice cero, este es el primero, luego el siguiente tendrá un índice de uno y así sucesivamente. Y recuerda que nuestro valor de estado en nuestro hook actual aquí es una matriz de los diferentes valores de estado. Entonces, currentHook.state con un índice de cero devolverá nuestro contador, currentHook.state con un índice de uno devolverá, en este caso, el clicker. Y eso es lo que ahora necesitamos tener en cuenta. Necesitamos almacenar de alguna manera este índice para que aquí sepamos a qué estado nos referimos realmente y queremos actualizar. La siguiente rama, que es el capítulo tres paso uno. Ese fue el paso final para el nuevo estado. Estamos revisando el capítulo tres, paso uno.

Tomamos el primer valor y luego lo comparamos con el valor que se pasa, es decir, el nuevo valor del estado. Y luego tomamos el estado anterior y el actual. Tenemos esta función auxiliar, stateStiffer, que simplemente hace una verificación simple en el estado anterior y el nuevo estado. Y luego, si se debe actualizar el estado, establecemos el valor del estado en nuestro hook. Entonces, el hook actual, currentHook, cambiamos ese valor para representar el nuevo estado. Y luego lo importante, para reflejar los cambios en nuestra página, necesitamos llamar a nuestra función de actualización. Y esa es la función que recordamos que se pasa hasta el final y que realmente realiza los cambios en nuestros elementos del DOM. Y, por supuesto, aquí es donde hacemos los cambios finales en el estado inicial. Y también devolvemos la función de actualizaciones. Y luego, lo último es devolver ese estado desde la función useState. Veamos qué significa esto para la aplicación en este estado actual. Cometí el error de decir que el contador debería funcionar. El contador no debería funcionar en este punto, y veremos por qué. Pero, si agrego un elemento ahora, podemos ver que el elemento se agrega correctamente a la lista de tareas pendientes. Pero algo extraño ha sucedido en nuestro campo de contador. Está tomando el estado que establecimos para nuestra lista de tareas pendientes y también lo ha puesto en el estado de nuestro contador. Claramente, eso no es lo que queremos. Y eso se debe a que nuestra implementación actual solo tiene en cuenta que el componente puede tener un estado por componente. Entonces, si puedes ver, si vamos al código, está mostrando eso. Entonces, esto es esencialmente, si miras en este common, cómo se ve nuestro componente de la aplicación. Tiene el contador en el setCounter, y luego el mismo componente, también tiene, bueno, en la aplicación son los elementos de la lista de tareas pendientes. Entonces, los elementos. Entonces, nuestro componente tiene dos estados, pero solo estamos actualizando un estado y asumiendo que el componente solo puede tener un estado. Estos dos estados están compartiendo el mismo estado en este momento. Entonces, lo que necesitamos hacer ahora es permitir que nuestra nueva función de estado maneje múltiples estados por componente. Para que cada tipo de estado se actualice con el valor correcto. Y algo importante a tener en cuenta es cómo React maneja esto, lo maneja secuencialmente, por índice. Entonces, este es el primer índice que tenemos, el índice cero, este es el primero, luego el siguiente tendrá un índice de uno y así sucesivamente. Y recuerda que nuestro valor de estado en nuestro hook actual aquí es una matriz de los diferentes valores de estado. Entonces, currentHook.state con un índice de cero devolverá nuestro contador, currentHook.state con un índice de uno devolverá, en este caso, el clicker. Y eso es lo que ahora necesitamos tener en cuenta. Necesitamos almacenar de alguna manera este índice para que aquí sepamos a qué estado nos referimos realmente y queremos actualizar. La siguiente rama, que es el capítulo tres paso uno. Ese fue el paso final para el nuevo estado. Estamos revisando el capítulo tres, paso uno.

16. Optimizando la Representación con el Módulo Diff

Short description:

Para optimizar la representación, necesitamos calcular qué debe volver a representarse en lugar de renderizar toda la página en cada actualización de estado. Comenzaremos implementando el módulo diff, que identifica cinco tipos de diferencias: nodo agregado, nodo eliminado, nodo reemplazado, actualización de nodo primitivo y actualización de props. El módulo diff incluye funciones auxiliares para crear objetos que describen las diferencias, como nodo agregado y nodo eliminado. Estos objetos contienen información sobre la posición y el tipo de la diferencia, así como cualquier carga necesaria. Al implementar el módulo diff, podemos determinar los elementos específicos que requieren volver a representarse en función de los cambios en el DOM virtual. Esta optimización mejora el rendimiento y evita representaciones innecesarias.

De acuerdo, la parte clave de este paso fue, en primer lugar, necesitamos de alguna manera rastrear el índice y almacenar el índice para cada estado que se crea. Entonces, tenemos un gancho actual que denota a qué gancho nos referimos y también creamos esto, en este punto, solo una referencia de índice de estado. Y estamos usando esta referencia de usar actual para asegurarnos de que los valores persistan y se actualicen y no permanezcan obsoletos. Entonces, tenemos nuestro valor de índice, que inicializamos en cero para comenzar. Y luego entramos en nuestra función useState, en la línea 29. Tomamos, recuerda que este nuevo estado se llamará para cada estado dentro de cada componente. Entonces, la primera vez que vemos un nuevo estado y un componente, vamos a entrar aquí. Vamos a tomar el índice de estado actual, que es cero en el primero. Luego, lo que vamos a hacer es, porque lo estamos inicializando aquí en su propia variable, luego vamos a aumentar el valor actual en uno. Entonces, cuando volvamos a ingresar a esta función para el siguiente nuevo estado que se llama, ese valor tendrá un índice de uno y así es como diferenciamos y mantenemos el índice a través de nuestro nuevo estado diferente. Entonces, tenemos el índice de estado que representa el índice correcto del estado que queremos y dónde necesitamos usar esto. Bueno, ahora, cuando tenemos un estado de gancho actual, recuerda que el estado es una matriz de todos los valores, usamos nuestro índice de estado para devolver el estado correcto y hacemos la comparación en el valor de estado correcto. La actualización sigue siendo la misma y luego, si ha habido cambios requeridos en nuestro actualizador, necesitamos aplicar esos cambios a nuestro estado en el gancho actual. Y luego, por supuesto, estamos devolviendo el estado específico en ese índice. Entonces, hay algunos cambios que deben hacerse, pero lo importante es almacenar ese índice y actualizarlo correctamente para cada llamada de la función useState. Y si vamos a nuestra aplicación, puedes ver que el contador ahora funciona y luego, si agregamos algo a nuestra lista de tareas pendientes, eso también funciona y no actualiza el contador porque estamos atendiendo diferentes estados dentro de un componente. Entonces, dejamos esto funcionando, ¿verdad? Pero ahora tenemos un problema, que cada vez que se actualiza un estado, volverá a representar toda la página. Y una forma en que puedes ver esto es cuando comienzas a escribir algo aquí, puedes ver que pierdo el enfoque y lo perderé cada vez que escriba algo. Y eso se debe a que cada vez, ¿verdad?, se vuelve a representar toda la página. Entonces, es un nuevo elemento completo que se coloca aquí, lo que significa que obviamente seguirá perdiendo el enfoque. Y además de eso, obviamente no es muy eficiente, ¿verdad?, volver a representar cada elemento en la página en cada actualización de estado. Entonces, nuestro objetivo ahora será pensar en cómo podemos calcular un poco mejor qué debe volver a representarse dentro de toda esta página y tratar de volver a representar solo las cosas que deben hacerlo. Y la primera parte en la que nos centraremos para eso se llama diff. Y dentro de este capítulo tres, paso uno, encontrarás un nuevo módulo aquí, que se llama diff. Y tal vez antes de revisarlo, vayamos a nuestro índice. Y por ahora, lo que agregamos en nuestro índice es solo un cálculo de la diferencia aquí, ¿verdad? Estamos llamando a esta nueva función que te explicaremos para obtener cuál es la diferencia entre nuestro vdum renderizable actual versus nuestro vdum anterior. Y por ahora, solo estamos registrando esta diferencia para poder verificar qué sucede. Y así que si vuelvo a mi aplicación, podemos ver aquí que tenemos un montón de elementos de diferencia y por ahora puedes ver que todos son props. Y echemos un vistazo al módulo diff donde tendrás que modificar cosas más adelante. Entonces, cuando pensamos en la diferenciación, pensamos en cinco tipos de diferencias que pueden ocurrir. Uno de ellos es nodo agregado, lo que significa que se agregó un nuevo nodo al vdum en una posición donde no había ningún nodo antes. Uno de ellos es nodo eliminado. Entonces, se eliminó un nodo en una posición específica donde solía haber un nodo. Uno de ellos es nodo reemplazado. Entonces, un nodo que estaba en la posición específica ahora cambió a un nodo completamente nuevo. Uno de ellos es actualización de nodo primitivo. Entonces, un nodo que tiene, por ejemplo, un texto específico ahora tiene un texto diferente. Y el último es actualización de props. Entonces, algunos de los props de un componente específico o elemento de etiqueta se han actualizado entre la representación anterior y la representación actual. Y dentro de los props, tenemos dos tipos diferentes. Uno es actualización, por lo que el prop ya existía, pero ahora tiene un valor diferente, o eliminación, el prop existía antes, pero ya no existe. Y para facilitar un poco la tarea aquí y evitar que tengas que pensar demasiado en algunas de las estructuras a medida que avanzas, creamos algunas funciones auxiliares donde creamos este tipo de objetos que nos ayudarán a describir nuestra diferencia. Entonces, por ejemplo, esto creará un nodo agregado de diferencia. Requiere tener un puntero Vedon, para que sepamos dónde buscar el elemento que queremos... En qué posición se debe agregar el nuevo elemento. Es de tipo de diferencia, no agregado. Y como carga útil, tiene el nodo que queremos agregar y el puntero del padre, por lo que es un poco más fácil encontrar dónde debemos agregar este nodo y agregarlo dentro del DOM real. Y hicimos lo mismo para nodo eliminado. Tiene el puntero Vedon y el tipo nodo eliminado, y no necesita ninguna carga útil. Y luego tenemos nodo reemplazado.

17. Creando el Div de Elementos Cambiados

Short description:

La función crea un div de todos los elementos que han cambiado entre la representación anterior y la representación actual. Toma el elemento V DOM renderizable actual y lo compara recursivamente con el V DOM anterior. El div es un array de elementos div, cada uno representando un tipo de cambio, como nodo reemplazado, actualización de nodo primitivo o div de props. La función también maneja el cálculo del div de props al comparar las props del elemento anterior y actual. La recursión permite recorrer el V DOM renderizable y construir el div de abajo hacia arriba. La función asegura que el puntero del padre se asigne correctamente para evitar problemas con la representación de componentes. El objetivo es optimizar la representación actualizando solo los elementos necesarios según los cambios en el V DOM.

para que podamos agregar el puntero Vedon y el nuevo nodo, el nodo antiguo, que también pasamos al payload y el puntero del padre, y su subtipo nodo-reemplazado. Y tenemos nuestra actualización de nodo primitivo, toma nuestro elemento actual y el nuevo elemento, que será básicamente esto, contendrá el valor de lo que tenemos que cambiar, y esto nos da el puntero Vedon aquí y el subtipo actualización de nodo primitivo. Y luego tenemos nuestro div de props, que se aplicará en un puntero Vedon específico para que podamos encontrar un componente donde aplicarlo. Es de tipo div de props, y como carga tiene props cambiadas, que es básicamente una mezcla de props eliminadas y props actualizadas. Entonces, para crear props eliminadas, solo necesitamos el valor antiguo y su tipo props-removed, y para props actualizadas, necesitamos el valor nuevo y antiguo, y lo pasamos al objeto para que podamos recuperarlos más adelante cuando intentemos aplicar esos div, y es de tipo div actualizado.

Y luego aquí, esto es algo que aún no necesitarás, pero lo necesitarás más adelante cuando intentemos aplicar estos div al DOM. El orden en el que los aplicamos importa, porque por ejemplo, si eliminamos un nodo, entonces, ya sabes, cambiará algunos de los índices. Así que creamos este pequeño array para explicar en qué orden deben aplicarse, y luego llegamos a nuestra función principal que vimos en el otro lado, cuyo objetivo es crear un div de todos los elementos que han cambiado entre la representación anterior y la representación actual. Y un div será solo un gran array de elementos div donde cada elemento es uno de los tipos que vimos antes. Y lo que esta función toma es nuestro elemento V DOM renderizable actual. Entonces, al principio, esto será todo el V DOM renderizable, y luego iremos recursivamente en esta función. Entonces, a medida que descendemos, ¿verdad?, serán subárboles de la raíz hasta que lleguemos a algunos de los elementos que alcanzan la condición de finalización. Entonces, por ejemplo, elementos primitivos, ¿verdad?, ya no tenemos más hijos para recorrer. Y luego volveremos a construir todo el div. Toma el V DOM para que podamos acceder al V DOM anterior para poder comparar cosas. Y por conveniencia, toma el puntero del padre, principalmente porque dentro de nuestro V DOM renderizable, como recordarás, ya no tenemos componentes. Entonces, eventualmente, tu padre podría no estar como dentro del V DOM renderizable, tu padre, tu padre directo, como si lo eliminas, solo tu propio índice del puntero podría no estar presente en el V DOM renderizable. Y podría ser algo por encima de él que lo representa. Entonces, eso evita que tengamos que buscar eso. Y ahora podemos pasar a crear nuestro div. Entonces, el primer paso es encontrar el elemento anterior de nuestro V DOM dot previous. Y aquí estaría tu primera tarea. Si no tenemos un elemento anterior, este será un tipo específico de div que queremos que agregues aquí. Y si tenemos un elemento anterior, entonces accederemos a su elemento punto porque este es un elemento V DOM. Entonces tiene el elemento y los hijos renderizados. Entonces, este es como el elemento final real que renderizaríamos. Y para el elemento V DOM renderizable actual, estos no tienen los hijos renderizados, por lo que es directamente el elemento. Y compararemos su tipo y si no coinciden en tipo. Entonces, por ejemplo, solía ser un primitivo y ahora es un div, entonces crearemos un tipo de div no reemplazado. Y si ninguna de estas condiciones es verdadera, continuamos hacia abajo. Y si ambos elementos son elementos primitivos, entonces queremos que reemplaces esta condición con la versión final de ella. Y esto debería crear una actualización de nodo primitivo. Entonces, tienes que pensar en qué condición aquí crearía una actualización de nodo primitivo. Y también hay un pequeño recordatorio de cómo se ve un nodo primitivo. Entonces, con suerte, será un poco más fácil de entender. Y luego aquí estamos tratando de calcular el div de props. Para hacer eso, lo que hacemos es buscar todas las claves entre las props del elemento anterior y las props del elemento actual. Y usamos un conjunto aquí para obtener un conjunto único, una colección de claves de props únicas. La idea aquí es que ambos pueden tener props diferentes, ¿verdad? Como tal vez el elemento anterior tenía más props que el actual, pero queremos recorrer todos ellos para asegurarnos de no perder ninguno cuando estemos calculando el div. Y luego recorremos todas estas claves. Los hijos se manejarán más adelante, así que por ahora los ignoramos. Y nuestro valor de prop actual es current element props de la clave. Nuestro valor de prop anterior, lo mismo, pero con el elemento anterior en su lugar. Y aquí, si no tenemos un valor de prop actual, entonces creamos un div de tipo eliminado para esta prop específica. Y si tenemos una propiedad actual, comparamos su valor con el valor actual, y si no son iguales, entonces creamos un div de tipo actualizado para ello. Y aquí creamos un array de div, para que podamos almacenar más elementos div dentro de esta función. Y si tuviéramos algún div de props cambiadas, entonces podemos crear un div de props, ¿verdad? Para que podamos realizar un seguimiento de todas las props que han cambiado. Y ahora la parte divertida, la recursión. Como dijimos, hasta ahora ignoramos los hijos. Aquí tomaremos nuestros hijos anteriores.

18. Recorriendo los Elementos y Calculando Diffs

Short description:

Recorremos todos los elementos entre los dos arrays, teniendo en cuenta las longitudes de los elementos anteriores y actuales. Si no hay un hijo actual, devolvemos un diff específico. Si hay un hijo actual, entramos en recursión, yendo más profundo en el subárbol. Llevamos un seguimiento del diff actual y agregamos los elementos diff calculados para el subárbol. Finalmente, devolvemos el diff final.

Nuevamente, esto es un poco extraño, ¿verdad? Pero estos son elementos VDOM regulares, por lo que estamos usando este renderizado de hijos para representar el resultado de llamar al componente o recorrer los hijos de un elemento y agregar punteros VDOM. Y en el que realmente queremos renderizar, hemos reemplazado props.children con lo que queremos, por lo que podemos usar props.children aquí. Y ahora queremos recorrer todos los elementos entre estos dos arrays. La forma en que decidimos hacerlo es mirar sus longitudes y tomar el máximo de las dos longitudes. Así nos aseguramos de que si este elemento anterior tiene más hijos que el actual, seguiremos recorriendo todos los hijos del anterior y viceversa, ¿verdad? Si este tiene más hijos que el anterior, entonces, porque estamos usando las longitudes máximas, nos aseguramos de recorrer todos ellos. Luego, recorremos nuestro índice y para cada uno de ellos, buscamos en los hijos actuales, en este índice y lo colocamos en este currentChild. Y si no tenemos un currentChild, eso también sería algo en lo que pensar, ¿qué significa eso en términos de un diff? Entonces aquí también deberíamos devolver un diff específico. Y si tenemos un currentChild, entonces podemos entrar en la recursión, ¿verdad? Podemos llamar a esta función nuevamente. Pero nuestro subárbol ahora está un nivel más profundo. Nuestro VDOM sigue siendo el mismo, ¿verdad? Seguimos accediendo a través del puntero VDOM. Así que está bien. Y nuestro puntero padre es el elemento actual en el que estamos en la recursión. Con esto, básicamente escribiremos, descenderemos por cada hijo de cada hijo de cada hijo hasta que lleguemos a los elementos diff que están arriba, incluido el nodo primitivo que no tiene hijos, ¿verdad? Para el nodo primitivo, no nos encontraremos con esto en absoluto. Y en algún momento, todos ellos volverán uno por uno a este diff de subárbol. Y lo que hacemos en este diff de subárbol es mantener el diff actual que ya teníamos, ¿verdad? Estos son todos los elementos diff que hemos calculado hasta ahora. Y estamos agregando todos los que se calcularon para el subárbol. Así que estamos seguros de tener una lista muy, muy larga de todos los elementos diff que encontramos al recorrer toda la estructura del árbol. Y una vez que tenemos nuestro diff final, simplemente lo devolvemos y estamos listos para continuar.

19. Aplicando Diffs al DOM

Short description:

Necesitamos entender los diferentes tipos de diffs y cómo aplicarlos al DOM. Los tres tipos principales son nodo añadido, actualización de nodo primitivo y nodo eliminado. Para un diff de nodo añadido, creamos un nuevo nodo cuando no hay un elemento anterior en esa posición. Para una actualización de nodo primitivo, comparamos los valores del elemento primitivo y creamos una actualización cuando el valor cambia. Para un diff de nodo eliminado, creamos una eliminación cuando no hay un hijo actual en una posición donde solía haber uno. Para aplicar el diff, utilizamos aplicadores de diffs, que son funciones que aplican tipos específicos de diffs al DOM. Los diffs se aplican en un orden específico y utilizamos un mapa de elementos renderizados para hacer un seguimiento de los elementos del DOM renderizados. Los aplicadores de diffs se llaman con el mapa de elementos renderizados y el elemento diff para aplicar los cambios. Ya hemos implementado un ejemplo de aplicación de un diff de actualización de nodo primitivo.

Y así, como recordatorio rápido, las tres cosas a las que nos gustaría que echen un vistazo, pensando en qué tipo de diff es cuando no podemos encontrar un elemento anterior. Pensando en qué condición llevaría a una actualización de nodo primitivo. Y pensando en qué significa si existía un hijo anterior pero no hay un hijo actual en la misma posición. Comencemos con lo que estamos viendo aquí y lo que tenías que hacer. La primera pregunta es qué sucede si no hay un elemento anterior en esta posición. Y si adivinaste que esto debería ser un nodo añadido, estás en lo correcto. Siempre que no haya un elemento anterior significa que el elemento que estamos tratando de agregar ahora no existía en el VDOM anterior, lo que significa que debemos crear un nodo añadido. En cuanto al elemento primitivo, ¿en qué condición consideramos que se actualizó un nodo primitivo? La solución aquí fue verificar el valor de cada elemento primitivo. Mientras este valor no cambie, sabemos que estamos renderizando lo mismo. Tan pronto como cambie, debemos crear la actualización de nodo primitivo. Y esto puede ser una simple comparación porque aquí, ¿verdad? Ambos son valores primitivos. Así que debería ser seguro compararlos. Y la última y más complicada parte probablemente sea aquí. ¿Qué sucede si no tenemos un hijo actual en la posición en la que solía haber uno? Y cuando eso sucede, significa que se eliminó un nodo del DOM. Así que creamos aquí un elemento diff de nodo eliminado. Ahora tenemos el diff correcto calculado. Y el siguiente paso será, ¿cómo aplicamos este diff al DOM? Si volvemos a nuestros controladores del DOM donde realmente implementamos las cosas que suceden dentro del navegador. Y vemos nuestra suscripción de renderizado. Ahora hemos agregado en la devolución de llamada que actualiza, que intentará actualizar el DOM, hemos agregado nuestro diff aquí. Y la idea es que en la primera renderización, todavía estamos haciendo lo mismo que antes. Pero después de eso, intentaremos aplicar el diff en su lugar. Así que no estamos agregando el hijo nuevamente o reemplazando el hijo como solíamos hacerlo. Pero ahora solo queremos aplicar los cambios que se mencionan en este diff. Así que veamos cómo estructuramos eso. Para ayudarte a realizar las tareas pendientes, decidimos crear esos aplicadores de diffs, que es un mapa donde las claves son el tipo de diff que estamos tratando de aplicar, y cada valor será una función que intentará aplicar el diff dado al DOM. Como puedes ver, no todos están completos. Pero está bien, los completaremos después. Pero ahora veamos dónde intentamos aplicarlos. Tenemos esta función apply diff aquí. Recibe el diff que acabo de mencionar y lo primero que hará, como mencionamos, es ordenarlos para asegurarnos de intentar aplicarlos en el orden correcto. Luego los revisaremos y para cada uno de ellos encontraremos el aplicador y lo llamaremos. Como puedes ver, siempre lo llamaremos con dos argumentos. El primero es un mapa de elementos renderizados, que es una conveniencia que decidimos crear, donde llevamos un seguimiento de los elementos del DOM reales que hemos renderizado. Y la idea del mapa es que asociará el puntero VDOM con los elementos reales renderizados dentro del DOM, para que podamos encontrarlos fácilmente para aplicar los cambios que necesitamos aplicar. Y el VDOM renderizable es útil a veces para encontrar información sobre ciertos elementos. Creo que tendremos un ejemplo de eso, así que podemos repasarlo tal vez con el ejemplo. Y finalmente, ya hemos implementado uno de ellos para ti. Así que puedes tener un ejemplo de uno simple que tal vez también te ayude a implementar los demás. No intentaremos que los implementes todos. No te preocupes. Este es el que aplica una actualización de nodo primitivo. Como se mencionó, ¿verdad? Recibe el mapa de elementos renderizados en el primer argumento. También recibiría el VDOM renderizable, pero eso no es útil para este caso. Y recibiría el puntero VDOM del elemento diff.

20. Aplicando Diffs y Actualizando Elementos Renderizados

Short description:

Para aplicar el diff de actualización de nodo primitivo, actualizamos el mapa de elementos renderizados con el nuevo valor del elemento. Para las actualizaciones de propiedades, iteramos a través de los cambios de propiedades y aplicamos los nuevos valores a los elementos correspondientes en el DOM. El diff de nodo añadido requiere convertir el nodo GSX a HTML y encontrar la posición correcta para insertarlo utilizando la función auxiliar findNextSiblingOfVDOMPointer. El mapa de elementos renderizados realiza un seguimiento de todos los elementos y debe actualizarse con cada elemento diff para garantizar un renderizado preciso.

Y este elemento diff específico, la actualización de nodo primitivo, viene con una carga útil que tiene un nuevo elemento. Así que también obtenemos eso. Lo que hacemos es tomar nuestro mapa de elementos renderizados, que contiene todos los elementos reales dentro del DOM, y accedemos a él para el puntero VDOM al que se refiere el diff, y actualizamos el valor de sus nodos, que básicamente es el texto que se renderiza, y colocamos dentro el nuevo valor del elemento y el nuevo elemento que recibimos de la carga útil. Así que eso debería reemplazar ahora para los nodos primitivos, eso debería reemplazarlos correctamente dentro del DOM, y tal vez podamos echar un vistazo rápido. Por ejemplo, este contador es solo un texto. Dentro de él hay un nodo primitivo. Y si intentamos hacer clic en más, eso funciona, está bien. Pero como puedes ver, esto no se actualiza porque esto es una actualización de propiedad. Así que aún no tenemos la implementación para eso. Esto tampoco se actualiza. Y, por ejemplo, esto tampoco se actualiza. Así que no podemos agregar elementos. Así que tendremos que resolver eso. Y lo primero en lo que nos gustaría que te fijes es en la aplicación de propiedades, que creo que es una de las aplicaciones de diff más simples que tenemos. Y al igual que con la actualización de nodo primitivo, solo se preocupará por el mapa de elementos renderizados. Obtiene el puntero VDOM de su diff. Y hay una carga útil. Obtiene los cambios de propiedades. Y el código que ya hemos escrito para ti es revisar todos estos cambios de propiedades. Y para cada uno de ellos, intentaremos aplicarlos. Cada cambio de propiedad tiene una clave, que es el atributo que debemos intentar reemplazar, un tipo de diff de propiedad que puede ser actualizado o eliminado. Puedes ignorar la eliminación. No te pediremos que lo hagas. Puedes concentrarte solo en la actualización. Y obtiene el valor antiguo y el valor nuevo. Y aquí está el código en el que nos gustaría que pienses. Lo primero que debes intentar es pensar en cómo aplicar este nuevo valor para este atributo al elemento correcto dentro del DOM, para lo cual el mapa de elementos renderizados debería ayudarte. Y si logras hacer eso, puedes ver qué debemos hacer para los controladores de eventos. Puede haber algo un poco específico que debamos hacer para ellos. Y lo último que puedes intentar si realmente eres un superhéroe y has pasado por ambos es el nodo añadido, que está aquí. Y este es mucho más complicado de aplicar, así que también necesita el mapa de elementos renderizados. Este también necesita el VDOM renderizable. Y luego, lo mismo, si el elemento tiene el puntero VDOM en el que queremos agregar el elemento, el nodo que se debe agregar y el puntero del padre para que sea un poco más fácil encontrar el padre. Pero aquí hay varias cosas en las que debes pensar. Lo primero es que este nodo es GSX, por lo que necesitaríamos que sea HTML antes de intentar insertarlo. Y luego necesitaríamos encontrar el lugar correcto para insertar el HTML que creamos. Y para eso, creamos una pequeña función auxiliar aquí, que se llama findNextSiblingOfVDOMPointer. Así que puedes llamarla, como ves, con las mismas cosas que recibe el aplicador de nodo añadido y un puntero VDOM y un puntero del padre. Y lo que esto devolverá es, dentro del DOM, qué elemento debería ser el siguiente hermano de este puntero VDOM para que sepas dónde insertarlo básicamente después. No vamos a repasar la implementación. No tenemos suficiente tiempo para eso. Pero, por supuesto, siempre puedes repasarla más tarde después de la masterclass. Y otra cosa de la que debes tener cuidado si llegas hasta allí es que algunos de los nodos en realidad no renderizan nada en el DOM. Por ejemplo, undefined es válido tenerlo dentro de esta función. Pero en realidad no debería renderizar nada dentro del DOM. Y la última parte es este mapa de elementos renderizados, donde mantenemos un índice de cada elemento. Necesitamos asegurarnos de actualizarlo cada vez que hacemos una actualización de elemento diff para que los siguientes tengan el mapa correcto. Y tal vez una última cosa sobre este mapa de elementos renderizados, por ahora, puede parecer un poco misterioso cómo funciona. Pero técnicamente, hasta ahora, lo principal de cómo funciona está aquí. Cada vez que intentamos renderizar algo, aquí, crearemos la versión HTML del elemento que recibimos.

21. Renderización de Elementos y Manejo de Efectos Secundarios

Short description:

Para la tarea de actualización de props, utilizamos la función apply prop al elemento HTML con la clave y el nuevo valor. Recuperamos el elemento del mapa de elementos renderizados basado en el puntero VDOM. Para los event listeners, eliminamos el antiguo listener antes de agregar uno nuevo. Para la tarea de nodo añadido, encontramos el elemento padre y el siguiente hermano utilizando funciones auxiliares. Renderizamos el nodo e lo insertamos antes del siguiente hermano. El mapa de elementos renderizados se actualiza en consecuencia. Los aplicadores de diff y otros detalles se pueden explorar en el repositorio. useEffect es un hook que permite a los componentes manejar efectos secundarios de forma independiente de la función de renderizado. Se puede utilizar para rastrear eventos, animaciones y almacenamiento local. Al usar useEffect, podemos persistir datos en el almacenamiento local y manejarlos por separado del renderizado. El código dentro de useEffect se activa en cada renderizado.

Y para este elemento, puntero de video, lo colocaremos dentro del mapa de elementos renderizados, el elemento renderizado. Esto nos permite mantener siempre un seguimiento de los diferentes elementos que estamos creando. Así que como resumen, espero que esté bien. Si eres un héroe, puedes probar esto. Y si eres un superhéroe, puedes probar el nodo añadido. Y luego te guiaré a través de la solución después. Y me doy cuenta de que olvidé lo que dije sobre el superhéroe. Todos ustedes son superhéroes por seguir estando aquí. Así que pasemos a la siguiente parte. Y te guiaré a través de las cosas que tenías que hacer. Me doy cuenta de que faltan algunos de los otros aplicadores de diff, pero era demasiado material para repasar. Así que siempre puedes ir al repositorio y probarlo. Como mencionó Straub, estamos pensando en crear también publicaciones de blog al respecto. Así que eso podría ser también una forma más fácil que hacerlo tú mismo con el repositorio, que debería salir más adelante. En cuanto a las props y específicamente las props actualizadas, que fue una de las tareas que tenías, para el caso normal, podemos usar prácticamente la misma función apply prop al elemento HTML que ya tenemos y darle la clave que queremos cambiar y para el valor, el nuevo valor. Y luego el elemento lo podemos obtener de nuestro mapa de elementos renderizados, el mapa de elementos basado en el puntero VDOM. Y la cosa extra en la que tenemos que pensar es en caso de que esto sea un event listener, si lo volvemos a agregar, entonces seguiría agregando y agregando y agregando event listeners y nunca los limpiaría, lo cual no funcionaría muy bien. Así que en su lugar, tenemos que eliminarlo primero. Así que creamos esta pequeña función Unity que básicamente hace element.removeEventListener y luego usa la clave final correcta para el evento y elimina esa antigua función que tenemos aquí. Y para este nodo añadido un poco más intenso, que está aquí, lo que hicimos es encontrar el elemento padre dentro del mapa de elementos renderizados a partir de su puntero padre. Y luego encontramos el siguiente hermano con esta función auxiliar que describimos, para saber dónde necesitaremos insertarlo. Y luego renderizamos nuestro nodo, ¿verdad? Así que eso tenemos aquí, elementos HTML listos. Y luego, si esto es algo que no se puede renderizar, probablemente undefined, entonces no lo renderizaremos, pero aún así actualizaremos nuestro mapa de elementos renderizados para que también tenga el undefined en esta posición específica. Y si no es algo que no podamos usar, entonces lo insertaremos en el elemento padre y insertaremos nuestro nodo recién agregado antes del siguiente hermano que obtuvimos de la función aquí arriba. Y luego no olvidemos también actualizar nuestro mapa de elementos renderizados, para asegurarnos de que siempre esté actualizado para los siguientes renderizados que podríamos hacer. Y sí, por falta de tiempo, no repasaremos todos los demás aplicadores de diff, pero puedes revisarlos por tu cuenta después. Y se lo entrego a Sean para la última parte sobre useEffect.

Entonces useEffect, este es el último capítulo que he hecho. Solo voy a hacer un paso en este capítulo. ¿Y qué es useEffect? useEffect es otro hook que proporciona React. Y un hook, nuevamente, es simplemente una función de JavaScript que contiene cierta lógica que queremos ejecutar. Y lo bueno de este hook useEffect es que permite a los componentes manejar efectos secundarios. Y lo que queremos decir con un efecto secundario es una lógica que queremos que sea independiente de la función de renderizado. Algunos ejemplos de seguimiento de eventos que queremos disparar de forma independiente de lo que se renderiza, animaciones y también almacenamiento local. Entonces, actualmente nuestra aplicación. Sí. Hola. Actualmente podemos hacer todo. Se ve genial. Pero si actualizo fuertemente, pierdo todos los datos porque no se están persistiendo. ¿Cómo podemos solucionar esto? Bueno, podemos usar el almacenamiento local para almacenar algunos datos que persisten al actualizar. Pero para hacer eso, debemos hacerlo en un efecto secundario. Entonces, debemos actualizar nuestro estado, pero también debemos manejarlo de forma independiente de lo que estamos renderizando. Y para eso podemos usar useEffect. Por ejemplo, tenemos un componente simple aquí. Aquí, tenemos el estado count y la función de actualización que ya hemos visto. Y aquí en esta parte, si configuro el elemento local storage set item de esta manera dentro de nuestro componente, el código aquí se activa en cada renderizado.

22. Uso del Hook useEffect para Efectos Secundarios

Short description:

Podemos mover esta línea dentro de un efecto de usuario y en este efecto de usuario hay una función. El hook useEffect nos permite especificar que la función solo se ejecute si hay cambios en el contador o en cualquier valor del array de dependencias. Encapsula la lógica como un efecto secundario que es independiente del renderizado del componente.

Ahora no queremos hacer eso a veces para este almacenamiento local. No necesitamos establecer el elemento en cada renderizado. ¿Cómo podemos hacer eso? Podemos mover esta línea dentro de un efecto de usuario y en este efecto de usuario hay una función. Así que veamos la construcción de ello. Nuevamente, como dices, es una función que llamamos, pero toma una función. Como primer elemento, nuevamente, y luego también el segundo elemento es un array de dependencias. Entonces, mirando el primer elemento, es una función, que es el efecto. Entonces, la función que queremos llamar para activar algún tipo de código o lógica. Entonces, en este ejemplo, tenemos una función que cuando se llama establece el elemento en el almacenamiento local. Y el segundo elemento es un array de dependencias. Y lo genial del hook useEffect es que podemos decirle a este efecto, este primer argumento, que es una función, que solo se ejecute si hay cambios en el contador o en cualquier valor que incluyamos en este array de dependencias. Entonces, esta función solo se llamará si el contador cambia. Y una cosa a tener en cuenta es que se llamará en el primer renderizado de la aplicación. Pero aparte de eso, el contador luego será, escuchará los cambios en el contador en este array de dependencias. Si hay un cambio, entonces afectaremos al almacenamiento local. Y eso es genial porque estamos encapsulándolo y permitimos que esta lógica sea un efecto secundario que es independiente del renderizado del componente. Si todavía estuviera aquí arriba, lo estableceríamos en cada renderizado, lo cual no es lo que queremos hacer. Pero esto nos permite manejar la lógica de forma separada e independiente.

23. Manejo de Efectos y Activación de Callbacks

Short description:

Necesitamos realizar cambios para manejar los efectos, que son funciones que deben ser llamadas después de que el DOM se vuelva a renderizar. El callback después de la actualización es responsable de volver a renderizar el DOM y activar los efectos. La función create hooks inicializa la lógica del use effect y pasa el mapa de hooks y el callback de registro de actualización. La función register hooks es responsable de llamar a los hooks en cada renderizado, y debemos hacer lo mismo para el use effect. Definimos un callback de efectos que activa todos los efectos actuales. Este callback es responsable de llamar a todas las demás funciones. Los efectos deben ser llamados después del renderizado, por lo que tenemos una función llamada register effects para después de la actualización del DOM que instancia la base de datos de efectos y activa el actual.

Entonces, pasemos a nuestro código base, que está aquí. Y puedes recordar del capítulo de use state que teníamos esta función de suscripción de inicio de renderizado, que se llama en cada renderizado. Y eso básicamente nos suscribe para escuchar los cambios de estado y manejar las actualizaciones que necesitamos para volver a renderizar nuestra aplicación y hacer cambios en el DOM. Ahora que estamos viendo el hook use effect, también necesitamos hacer algunos cambios aquí para tenerlo en cuenta. Lo importante de saber es que mencioné antes, pero queremos que nuestros efectos se activen después del renderizado. Un buen ejemplo de por qué, porque con las animaciones, por ejemplo, para que la animación funcione correctamente, la lógica necesita saber qué hay en la página para poder actualizar los elementos correctos. Entonces sabemos que necesitamos llamar a nuestros efectos, que son esas funciones que contienen la lógica específica que queremos activar, sabemos que necesitamos llamarlos después de que nuestro DOM se vuelva a renderizar. Entonces, si ves aquí, estamos llamando esto después de la actualización, este callback de actualización es responsable de volver a renderizar el DOM y calcular nuestras diferencias. Y luego, después de la actualización, es donde vamos a activar nuestros efectos. Entonces, todas esas funciones y nuestros componentes que queremos manejar de forma independiente al renderizado o después del renderizado. ¿Cómo lo hacemos? Entonces, lo que está sucediendo en esta actualización, simplemente es un callback. Es una función que activará todos los efectos, que son funciones. Básicamente, estamos activando una función que luego activa todos nuestros efectos, que también son funciones. Y así es como implementamos todos nuestros efectos cuando la aplicación, después de que la aplicación se renderiza. Entonces, nuevamente, recuerda que tenemos esta función register hooks, que es responsable de llamar a los hooks en cada renderizado, cada componente. Entonces, recuerda que teníamos aquí, así es como pasamos el puntero de lectura específico para que podamos instanciar el hook para cada componente. Y debemos hacer lo mismo para nuestro use effect. Y debemos asegurarnos de que los datos correctos también se estén pasando desde este make register hooks para que también podamos crear nuestra lógica de use effect. Y luego, uno aquí. Sí, similar a nuestra lógica de use state, tenemos otra función de orden superior, por lo que una función que devuelve una función. La primera función se llama en ese renderizado inicial. Configura todo en el primer renderizado para que sepamos qué está sucediendo, cómo manejar las cosas. Puedes ver que está tomando ese callback que vamos a actualizar. Recuerda que este es el callback, la función que contiene todas las funciones que queremos ejecutar. La función que contiene todos los efectos que queremos activar. Y nuevamente, está tomando el mapa de hooks para que sepamos cómo recuperar los hooks específicos para cada componente, o como una base de datos de hooks. Y entramos aquí. Aquí es donde estamos definiendo ese callback de efectos, esa función de todas nuestras funciones. Lo establecemos como un valor ficticio al principio. Y luego creamos otra función que se llamará, que es esencialmente responsable. ¿Es esa una función que activa todos los efectos actuales? Esta es la función que llamará a todas las demás funciones que hemos creado. Observa cómo, por lo que hay muchas funciones que llaman a funciones, pero lo importante de recordar es que tenemos esta única función que es responsable de llamar a todas las demás funciones y los efectos deben ser llamados después del renderizado. Entonces, después de la actualización. Entonces tenemos esta función register effects para después de la actualización del DOM, que crea una función que se puede llamar. Y aquí podemos ver que estamos instanciando la enorme base de datos de todos nuestros efectos. Y estamos activando el actual, y luego también estamos agregando el callback que se pasa a través de él.

24. Manejo de las Funciones y Dependencias de UseEffect

Short description:

Esta es la función que se activará cuando hagas referencia al use effect en tu componente. Es específica para cada hook dentro de cada componente y obtiene el puntero VDOM. Instanciamos el hook actual y devolvemos una función que toma el callback del efecto y el array de dependencias. Manejamos la función use effect almacenando el índice y usándolo para obtener el efecto anterior. Incrementamos el índice actual para cada efecto posterior. Verificamos las dependencias y actualizamos los efectos en el valor del hook actual en el índice específico. Establecemos el valor de las dependencias con las nuevas dependencias para futuras comparaciones.

Similar al useState, esta función en la línea 93 es la que se llama cuando haces referencia al use effect en tu componente. Esta es la función que se activará y es específica para cada hook dentro de cada componente. También obtiene el puntero VDOM para saber a cuál nos referimos y es el primer renderizado. Instanciamos el hook actual tomando el puntero VDOM y aplicándolo al mapa de hooks, obteniendo así una referencia específica para ese hook en relación con su componente. Luego, devolvemos una función que toma el callback del efecto, es decir, la lógica específica que queremos que ocurra, y el array de dependencias, que es un array de los valores a los que estamos escuchando. Escuchamos los cambios para... Sí, mi consejo aquí es leer las pistas y también hacer referencia a cómo hicimos useState, ya que hay muchas similitudes. También hemos creado esta función auxiliar, nuestras dependencias iguales, para que puedas comparar fácilmente la dependencia y realizar cambios en función de eso, el resultado de esta función. En este siguiente paso y nuestros pasos finales, que es el último código que escribirás, queremos manejar nuestro, específicamente nuestro use effect. Aquí, también debemos recordar registrar nuestros use effects y asegurarnos de que los datos se pasen correctamente a través de los pasos. Pero sí, mira cómo se hace para useState. Eso es un buen consejo. Ahora te llevaré rápidamente a través de la solución y luego terminaremos. La solución está disponible en el capítulo cuatro, paso dos. Si revisamos esa rama y vamos al código, el primer punto de partida fue en esta función MakeRegisterHooks. Y necesitábamos hacer algo similar a useState. Necesitábamos llamar a nuestra función MakeUseEffect y darle el puntero VDOM y el IsFirstRender, para poder crear los use effects para cada componente específico. También necesitábamos reemplazar el UseEffect en nuestro reemplazador global de hooks para que cada vez que se llame al UseEffect, usemos el que tiene los datos y la información correctos. Y otra cosa importante fue que ahora también necesitamos esta función MakeUseEffect disponible. Así que tuvimos que agregarla donde la estamos llamando y en la función createHooks aquí abajo. Esas son las adiciones que se requieren en estas dos funciones. Estamos llamando a las cosas en el orden correcto. Y luego, cuando llegamos al punto más interesante, que son nuestras funciones UseEffect, similar a State, necesitamos almacenar el índice porque, al igual que State, podemos tener múltiples efectos para cada componente. Nuevamente, lo establecemos en cero. Creo que esto probablemente es redundante, como se menciona en los comentarios, pero probablemente, sí, creo que solo estábamos tratando de protegernos. Podrías establecerlo en cero. Y luego, en nuestra función UseEffect real, es decir, la función que se llama cuando llamamos a UseEffect en nuestro componente, instanciamos el índice del efecto haciendo referencia a la referencia. Obtenemos el efecto anterior usando ese índice. Si no existe para que funcione la función de comparación, lo establecemos como un objeto vacío. Incrementamos el índice actual porque, nuevamente, esto se llamará una vez para el primer efecto en nuestro componente, y luego lo incrementamos para el siguiente, que es uno. Entonces, cuando se llama al siguiente UseEffect en un componente, el valor actual sería uno, que usamos aquí, y luego lo incrementamos nuevamente a dos y así sucesivamente. Verificamos nuestras dependencias. Si son iguales, no nos importa, simplemente retornamos, excluimos el componente y no hacemos nada. Si son diferentes, necesitamos actualizar nuestros efectos en el valor del hook actual y lo hacemos en un índice específico. Así es como lo hacemos con useState. Y luego, sí, establecemos en ese valor de las dependencias con nuestras nuevas dependencias. Entonces, esto se puede usar para la próxima llamada del use effect. Así que podemos hacer una comparación nuevamente en el futuro.

25. Manejo de Efectos y Limpieza de Hooks

Short description:

Manejamos los efectos llamándolos después de que se actualice el DOM. La función de utilidad nos permite agregar efectos a una base de datos de devoluciones de llamada, que se activan mediante una función llamada después de la actualización del DOM. Esto asegura que los efectos se manejen correctamente. Si estás interesado en construir tu propio React, hay un paso incompleto en la rama en la que te encuentras actualmente. Implica limpiar los hooks y restablecerlos cuando sea necesario. Una vez completado, la rama final contiene la lógica completa de tu propio React. Gracias por tu tiempo y paciencia. Planeamos publicar publicaciones de blog con explicaciones detalladas de cada capítulo y un mapa visual para ayudar a comprender el flujo de las llamadas a funciones. Gracias por unirte a nosotros y que tengas una excelente noche.

Y nuevamente, recuerda que queremos llamar realmente a nuestros efectos después de que se actualice el DOM. Creamos esa función de utilidad que nos permite agregar nuestro efecto a esa especie de base de datos más grande de devoluciones de llamada. Entonces, la única función que activa todos los efectos, luego agregamos nuestra devolución de llamada de efecto a esa lista, pero se llama después de que el DOM se actualiza realmente. Lo hacemos poniéndolo en una función, dándoselo a este registro de efecto después de la actualización del DOM y cuando se llama a esa función, en realidad llama a la devolución de llamada de efecto que estamos pasando aquí. Y así es como manejamos un useEffect.

Ahora puedes ver, voy a la aplicación y agrego y ahora hago una actualización completa. Los datos todavía están ahí porque la función de almacenamiento local está en el useEffect y eso funciona correctamente ahora. Un minuto, no quiero retenerte más, ya te has quedado tanto tiempo. Pero muchas gracias, esto fue una cantidad increíble de información en un período de tiempo tan corto. Realmente aprecio tu paciencia. El plan es que publiquemos una serie de publicaciones de blog que pasarán por cada capítulo en detalle y también incluirán un mapa visual porque creo que dijimos la palabra función como un millón de veces. Un mapa visual que te permita seguir el flujo de cada llamada de función un poco mejor y más claro porque eso es un punto clave y también un punto de bloqueo clave para comprender la infraestructura completa de esto, cómo funciona React. Hay muchas funciones de orden superior.

Y si estás realmente interesado y quieres seguir construyendo tu propio React, la rama en la que te encuentras actualmente es un paso incompleto y es el último paso, se trata de limpiar los hooks. Entonces, con cada hook, quieres restablecer ese hook cuando un componente se desmonta o antes de que se verifiquen las dependencias, porque, por ejemplo, si tienes un temporizador en tus useEffects, quieres borrar ese temporizador antes de que se cree un nuevo temporizador. Entonces, el capítulo cuatro, paso dos se encarga de eso y una vez que hayas terminado por completo, está la rama final y esa contiene la lógica completa de tu propio React. Sí, así que creo que se enviará el formulario de comentarios, que también tendrá enlaces a la grabación de esta sesión y una grabación más editada estará disponible, creo que en una semana aproximadamente. Sí, pero gracias por tu tiempo. Espero que no haya sido demasiado loco en un lunes. De verdad, muchas gracias a todos por quedarse con nosotros durante tanto tiempo y pasar por todo esto juntos. Creo que fue divertido, pero definitivamente fue intenso, creo que para nosotros y probablemente para ustedes también, y que tengan una buena noche. Traten de no soñar demasiado con React por ahora, al menos hasta mañana. Y trataremos de crear esta serie de publicaciones de blog más adelante para que haya una versión a un ritmo más lento de lo que acabamos de pasar, adiós adiós.