¿No puedes usar Hooks condicionalmente... o sí puedes?

Spanish audio is available in the player settings
Rate this content
Bookmark

Es la regla número uno de los hooks: "Solo llama a los hooks en el nivel superior".


Pero ¿qué pasa si te dijera que esta regla no se aplica a todos los hooks? Uno de ellos realmente se puede usar de forma segura de manera condicional.


Para entender cómo useContext es diferente de otros hooks, y por qué está exento de esta regla importante, necesitamos saber por qué existe esta regla en primer lugar. Construiremos nuestro propio modelo mental del comportamiento de renderizado de React, enfocado en cómo React realiza un seguimiento de los datos en tiempo de ejecución: props, estados, refs... y valores de contexto.

28 min
02 Jun, 2023

Video Summary and Transcription

La charla discute el uso del hook Use en React y su capacidad de ser utilizado de forma condicional. Explica el concepto del árbol de fibra y cómo se almacenan los valores de los hooks en la memoria. La charla también profundiza en el uso condicional de useContext y cómo difiere de useState. Explora el proceso de actualización de los valores de contexto y la optimización del renderizado de contexto. Se enfatiza el papel del proveedor en la gestión de los valores de contexto y el renderizado.

Available in English

1. Introducción al Hook Use

Short description:

Hace unos meses, el equipo principal de React propuso pedir la opinión de la comunidad sobre la idea de agregar un nuevo hook, el Hook Use. Use tendría una habilidad especial. Podríamos usarlo condicionalmente. En la propuesta, luego aprendimos que Use no solo obstaculizaría las promesas, sino también otras cosas, como los valores de contexto.

¡Hola a todos, soy Charlotte, y hoy vamos a desafiar las leyes de los hooks juntos! Hace unos meses, el equipo principal de React propuso pedir la opinión de la comunidad sobre la idea de agregar un nuevo hook, el Hook Use. Una versión exclusiva de React de Await que desempaqueta promesas, lo que nos permite obtener datos sincrónicos y usarlos directamente en nuestros componentes. No voy a profundizar en este hook hoy, pero hay algo sobre este hook que me interesa. Use tendría una habilidad especial. Podríamos usarlo condicionalmente. ¿Qué? ¿Cómo es posible? Solo hay dos reglas con respecto a los hooks. Regla número uno, solo llamar a los hooks desde funciones de React, como componentes de función y otros hooks, y regla número dos, no llamar a los hooks condicionalmente. ¡Solo dos reglas, y este hook estaría exento de la mitad de ellas? Y empeora. En la propuesta, luego aprendimos que Use no solo obstaculizaría las promesas, sino también otras cosas, como los valores de contexto. Podríamos leer valores de contexto con Use, al igual que lo hacemos con useContext.

2. Comprendiendo el Uso Condicional del Contexto

Short description:

Para entender por qué se puede usar el contexto de uso condicionalmente, primero debemos entender por qué otros hooks no pueden. Cuando construimos nuestra aplicación por primera vez, React crea un árbol de fibra para realizar un seguimiento de nuestros componentes. Cada componente está representado por un objeto de fibra que contiene información sobre el componente. El árbol de fibra ayuda a React a determinar qué elementos deben renderizarse y actualizarse en el DOM. Cuando instanciamos un componente de React, se agrega una nueva fibra al árbol. La fibra contiene el tipo, las props y la posición del componente en el árbol.

Entonces, déjame entender esto correctamente. Esto significa que podríamos leer los valores de contexto condicionalmente, y de hecho, ya hemos aprendido en este tweet de Andrew Clarke que ya podemos hacerlo. Ya podemos llamar al contexto de uso condicionalmente. Pero ¿por qué? ¿Por qué se puede usar el contexto de uso condicionalmente, mientras que otros hooks no pueden? Esa es la pregunta que vamos a intentar responder hoy.

Para entender por qué se puede usar el contexto de uso condicionalmente, primero debemos entender por qué otros hooks no pueden. Y para entender esto, debemos entender cómo funcionan los hooks. ¿Dónde se almacenan los datos de un hook? ¿Cómo hace React para realizar un seguimiento de nuestros datos a lo largo del tiempo y las renderizaciones? Para entender la diferencia del uso del contexto, primero debemos entender React. Así que comencemos con esta primera pregunta.

¿Dónde se almacenan los datos de nuestro hook? ¿Dónde se almacenan los datos de nuestro componente? Cuando construimos nuestra aplicación por primera vez, React va a construir este árbol virtual compuesto por nuestros componentes de React. Este árbol se llama árbol de fibra. El árbol de fibra realiza un seguimiento de los componentes de React que componen nuestra aplicación. A partir de este árbol, React va a inyectar nuestros elementos HTML en el DOM para mostrar nuestra aplicación en la pantalla. El árbol de fibra mantiene en memoria información sobre nuestros componentes, sus datos, sus props y sus estados a lo largo del tiempo y las renderizaciones. De esta manera, cuando ocurre una renderización, React sabe qué elementos han cambiado, cuáles deben renderizarse y qué información debe actualizarse en el DOM.

Entonces, la primera vez que construimos nuestra aplicación, React crea este árbol de fibra. Cada vez que instanciamos un componente de React, React agrega un nodo al árbol. A este nodo se le llama fibra. Echemos un vistazo a uno de ellos. Echemos un vistazo a una fibra de este componente de saludo. Cuando instanciamos el saludo, estamos usando esta sintaxis JSX, y JSX es simplemente azúcar sintáctica y es equivalente a la llamada de esta función JSX, o createElement hasta React 17. Y esta función JSX, cuando se ejecuta, creará, agregará una nueva fibra al árbol. Entonces, cuando instancias un componente con esta sintaxis JSX, en realidad estás agregando un nodo al árbol. Creas una nueva fibra.

Ahora, ¿cómo se ve realmente una fibra? Bueno, una fibra es simplemente un objeto que contiene información sobre un componente. Entonces, si observamos esta fibra de saludo, tenemos su tipo, tenemos sus props, los datos de las props se mantienen en memoria dentro de cada fibra, junto con un montón de otros estados y banderas para que React realice un seguimiento, y finalmente, tenemos su posición dentro del árbol de fibra. Hablando del árbol de fibra, veamos cómo se construye. Veamos qué sucede en el primer paso cuando se construye nuestro árbol de fibra. Vamos a recorrer nuestro código, y cada vez que instanciamos un componente de React con esta sintaxis JSX, React va a agregar una fibra al árbol.

Entonces, primero tenemos este componente de la aplicación que tiene el nombre de usuario en este estado que pasa a este componente de saludo, que lo muestra en un párrafo, y finalmente, tenemos este botón al que podemos hacer clic para cambiar nuestro nombre de usuario. Y aquí vamos.

3. Comprendiendo el Árbol de Fibra y los Hooks

Short description:

Hemos construido nuestro árbol de fibra e inyectado nuestros componentes en el DOM. Los valores de los hooks se almacenan en memoria dentro de cada fibra individual como una lista enlazada. El componente de función no retiene datos; la fibra sí lo hace. Al ejecutar la aplicación, los valores almacenados en la fibra se pasan a la función.

Hemos construido nuestro árbol de fibra. ¿Y ahora qué? Este árbol todavía es virtual. Aún no hemos mostrado nada en el DOM. Entonces, ¿qué va a hacer React? Va a inyectar nuestros componentes en el DOM, pero no todos ellos. Algunos de estos componentes son funciones puras de React. Este componente de saludo, por ejemplo, es un componente puro de React. No existe en el DOM. No es un elemento HTML. Entonces, lo que React va a hacer es recorrer nuestro árbol de fibra y cada vez que encuentre un elemento HTML, lo va a inyectar en el DOM. Así que nuestro párrafo y nuestro botón. Y ahora nuestra aplicación está en vivo en la pantalla.

Entonces, nuestros componentes data, nuestras props, se mantienen en memoria dentro de cada fibra. Ahora, ¿qué pasa con los hooks? Estamos aquí para hablar de los hooks, ¿verdad? Así que agreguemos un segundo estado aquí. ¿Dónde se almacenan esos dos valores? Bueno, lo adivinaste. Los valores de los hooks también se almacenan en memoria dentro de cada fibra individual, pero no de cualquier manera. Los valores de los hooks se almacenan dentro de una lista enlazada, donde cada valor apunta al siguiente uno. Estos valores luego son leídos por los hooks en el orden en que se llaman. Una cosa que debes entender aquí es que este componente de función, app, es solo una función. No retiene data. UseState no retiene data. La fibra sí lo hace. Cuando ejecutas la aplicación, ejecutas esta función y le pasas los valores que se almacenaron en memoria dentro de la fibra. Así que ejecutemos la aplicación por primera vez. Construyamos nuestra fibra. Ejecutamos la aplicación. Vamos a estar escribiendo esto. Este useState escribirá ese valor predeterminado en la fibra en el orden en que se llaman. Así que primero tenemos el nombre, que se escribirá en el primer elemento de la lista enlazada ya que está vacío hasta ahora, Rachel. Luego tenemos la edad, que se escribirá en el elemento actual de la lista enlazada, .next. Así que el segundo, 29.

4. Comprendiendo los Hooks y el Uso Condicional

Short description:

¿Qué sucede después de la renderización? ¿Puedes ver en este esquema por qué no puedes llamar a los Hooks de forma condicional? Intentemos llamar a este estado de nombre de forma condicional basado en este primer valor booleano. Tenemos este error que probablemente ya hayas encontrado en tu vida como desarrollador de React. Los Hooks dependen del orden en el que se llaman. Todos son interdependientes en sus listas enlazadas. Por eso no puedes usarlos de forma condicional.

¿Qué sucede después de la renderización? ¿Qué sucede si hacemos clic en este botón aquí y cambiamos nuestro primer estado, nuestro nombre de usuario? Vamos a renderizar. Vamos a ejecutar la aplicación y pasarle los valores que se mantuvieron en memoria dentro de la fibra. Entonces, primero el nombre se leerá en el primer elemento de la lista enlazada y la edad en el segundo. ¿Puedes ver en este esquema por qué no puedes llamar a los Hooks de forma condicional? Los Hooks dependen del orden en el que se llaman. Entonces, si en la siguiente renderización agregas o eliminas un Hook, cambias el orden y los datos que obtienes no son los correctos.

Intentemos hacerlo. Intentemos llamar a este estado de nombre de forma condicional basado en este primer valor booleano que es originalmente igual a falso. Rendericemos la aplicación por primera vez. Entonces, primero tenemos shuname que escribirá falso en el primer elemento de la lista enlazada. Y no cumplimos esta condición, así que pasamos a la edad que escribirá 29. ¿Qué sucede si hacemos clic en este botón aquí y cambiamos nuestro primer booleano a verdadero? Renderizaremos la aplicación y le pasaremos estos dos valores. Entonces, primero shuname leerá verdadero en el primer elemento de la lista enlazada. Luego, esta vez cumplimos esta condición, así que tenemos nombre que leerá 29. Sí, el nombre será 29 y luego tenemos la edad que puede encontrar su valor en cualquier lugar y sacarnos de quicio. Tenemos este error que probablemente ya hayas encontrado en tu vida como desarrollador de React. Los Hooks dependen del orden en el que se llaman. Todos son interdependientes en sus listas enlazadas. Por eso no puedes usarlos de forma condicional.

5. Comprendiendo el Uso de useContext

Short description:

¿Y qué pasa con useContext entonces? ¿Por qué se puede usar useContext de forma condicional? Vamos a modificar nuestro ejemplo un poco y usar proporciona nuestro nombre de usuario en este valor de contexto. La respuesta se encuentra en nuestro árbol de fibra. Así que construyámoslo. Primero tenemos estos objetos de contexto, luego tenemos la aplicación que todavía tiene el nombre de usuario en este estado que pasa esta vez en props al proveedor de contexto. Debajo del proveedor tenemos saludos que ahora es un consumidor de contexto. Lee el valor de contexto del valor de nombre de usuario del contexto y lo pasa a este párrafo. Y finalmente, terminamos con este botón que podemos hacer clic para cambiar nuestro valor de contexto.

¿Y qué pasa con useContext entonces? ¿Por qué se puede usar useContext de forma condicional? Vamos a modificar nuestro ejemplo un poco y usar proporciona nuestro nombre de usuario en este valor de contexto. La respuesta se encuentra en nuestro árbol de fibra. Así que construyámoslo. Primero tenemos estos objetos de contexto, luego tenemos la aplicación que todavía tiene el nombre de usuario en este estado que pasa esta vez en props al proveedor de contexto. Debajo del proveedor tenemos saludos que ahora es un consumidor de contexto. Lee el valor de contexto del valor de nombre de usuario del contexto y lo pasa a este párrafo. Y finalmente, terminamos con este botón que podemos hacer clic para cambiar nuestro valor de contexto.

6. Comprendiendo el Uso Condicional de useContext

Short description:

¿Puedes ver en este esquema por qué se puede usar useContext de forma condicional? useContext lee y almacena su valor dentro de un objeto de contexto ubicado fuera del árbol, sin relación con otros hooks. Al llamar a useContext, se pasa el objeto de contexto como argumento, lo que permite acceder directamente al valor. Por otro lado, useState se basa en el orden para determinar su valor, ya que no hay identificadores para diferenciar múltiples instancias. Esta distinción permite el uso condicional de useContext.

¿Puedes ver en este esquema por qué se puede usar useContext de forma condicional? Agreguemos aquí un segundo estado. Los valores de los hooks como useState o useEffect leen y almacenan su valor dentro de la lista enlazada donde los hooks son interdependientes y donde los demás importan. Por otro lado, useContext lee y almacena su valor dentro de un objeto de contexto que está ubicado fuera del árbol, fuera de la lista enlazada. useContext no está relacionado con otros hooks de la misma manera que useState. Por lo tanto, puedes llamarlo condicionalmente todo lo que quieras. Simplemente no afectará a otros hooks.

Y eso es algo que también puedes ver en el código. Echa un vistazo más de cerca al código. Observa cuando llamas a useContext, le estás pasando como argumento el objeto de contexto. Le estás diciendo, ve a verificar tu valor aquí mismo en este objeto. Está codificado de forma fija. Por otro lado, useState no recibe ninguna variable clave codificada de forma fija para encontrar su valor en. Todo lo que recibe es la lista de valores de todos los hooks de la fibra. Y este useState es igual que este otro. No hay un identificador para diferenciarlos. Entonces, ¿cómo sabe cuál de estos valores le pertenece? Se basa en el orden. Esa es la implementación que se decidió. Por eso se puede usar useContext de forma condicional. Por eso useContext es diferente.

7. Comprendiendo la Actualización de los Valores de Contexto

Short description:

Para entender cómo se actualiza un valor de contexto, necesitamos entender cómo se actualiza cualquier valor regular. Cuando cambiamos el valor de contexto, React calcula una nueva versión del árbol de fibra que corresponde al cambio. Compara este nuevo árbol con el anterior y aplica las diferencias al DOM. Sin embargo, solo se renderizan los componentes que pueden haber cambiado, no todos los componentes. Este proceso de cálculo implica duplicar el árbol de fibra, actualizarlo para reflejar el cambio, marcar la fibra que contiene el estado cambiado y recorrer el árbol para decidir qué componentes renderizar.

Pero algo parece estar faltando. ¿Cómo funciona exactamente, verdad? El valor de contexto se encuentra dentro de este objeto. Pero si este objeto está ubicado fuera del árbol, ¿cómo se actualiza? ¿Y cuál es realmente el papel de este proveedor aquí? Para que nuestra demostración sea completa, me gustaría profundizar un poco más si les parece bien, y realmente entender cómo se actualiza un valor de contexto, cómo funciona un valor de contexto por debajo.

De acuerdo, chicos, los próximos minutos van a ser bastante intensos. Para entender cómo se actualiza un valor de contexto, primero debemos entender cómo se actualiza cualquier valor regular. Así que vamos a obtener algo de teoría aquí sobre el comportamiento de renderizado de React. Así que tengan paciencia. Muy bien, ¿cómo se actualiza un valor de contexto? Vamos a hacer clic en nuestro botón aquí y cambiar nuestro valor de contexto. Veamos qué sucede. Vamos a volver a renderizar. Disparamos un estado establecido. Lo que va a suceder es que vamos a calcular una nueva versión de nuestro árbol de fibra que corresponde al cambio que hemos realizado en nuestro nuevo estado, nuestra nueva representación. Una vez que se haya completado, React comparará este nuevo árbol con el de la orden anterior y aplicará las diferencias al DOM. Pero cuando calculamos este nuevo árbol de fibra, en realidad no renderizamos cada componente de nuestra aplicación, eso podría ser ineficiente, solo los que pueden haber cambiado. Veamos cómo se realiza este proceso de cálculo paso a paso.

Así que hacemos clic en este botón aquí para cambiar nuestro valor de contexto. Vamos a cambiar para desencadenar un estado establecido. Vamos a renderizar. En este punto, suceden varias cosas. Primero, como dijimos, vamos a duplicar nuestro árbol de fibra. Vamos a actualizar este nuevo árbol de fibra para que corresponda al cambio que hemos realizado. Pero hasta ahora, es lo mismo. Es solo una copia. Segundo, vamos a marcar la fibra que contiene el estado que acaba de cambiar como necesidad de renderizar. Así que a este componente de la aplicación, esta fibra de la aplicación, vamos a agregarle esta pequeña bandera de renderizado. Y finalmente, vamos a recorrer nuestro árbol. Vamos a visitar cada fibra. Y para cada una de ellas, nos preguntaremos, ¿debemos renderizar estos componentes? Si es así, los renderizaremos. De lo contrario, abandonamos. Esperamos, salimos.

8. Renderizando el Componente App

Short description:

Comenzamos en la parte superior de nuestro árbol con la primera aplicación de fibra. La aplicación se marca para volver a renderizarse, por lo que la volvemos a renderizar.

No renderizamos. Y comenzamos en la parte superior de nuestro árbol con la primera aplicación de fibra. Así que usemos esta pequeña bandera de trabajo en progreso solo para tener en cuenta qué fibra estamos visitando actualmente. Visitando. Entonces, la aplicación. ¿Deberíamos renderizar la aplicación? Hay dos criterios para que un componente se renderice. Y si cumple alguno de ellos, renderizamos este componente. El primero es estar marcado para volver a renderizarse. Y la aplicación fue marcada para volver a renderizarse. Así que está bien. Volvemos a renderizar la aplicación. Agreguemos algo de color a este esquema. Pongamos en azul las fibras que se volvieron a renderizar solo para tenerlo en cuenta. Así que hemos vuelto a renderizar la aplicación.

9. Ejecución de Componentes de Función

Short description:

Ejecutar componentes de función significa ejecutar la aplicación y pasar los valores almacenados en la fibra. Al renderizar la aplicación, se crean nuevas fibras para todos los componentes instanciados con la sintaxis JSX.

¿Qué significa esto? Significa ejecutar sus componentes de función. Entonces ejecutamos la aplicación y le pasamos los valores que se guardaron en la memoria dentro de la fibra. Primero, vamos a leer el último valor de nombre de usuario que acaba de cambiar. Y luego vamos a través de todo este JSX. Y aquí mira. Mira este componente de saludos, estamos usando la sintaxis JSX aquí. Y recuerda que JSX es equivalente a la llamada de esta función JSX que crea fibras. Entonces, lo que esto significa es que en nuestro nuevo árbol para estos componentes de saludos, vamos a descartar completamente la fibra anterior y agregar una completamente nueva. Este es un nuevo objeto. Y algo, sí, pongámoslo en naranja. Las nuevas fibras están en naranja solo para tenerlo en cuenta. Algo que debes notar aquí y que será útil más adelante es que al crear una nueva fibra para los saludos, también estamos creando un nuevo objeto de props. Este es un objeto completamente nuevo. Será útil más adelante. Entonces, al renderizar la aplicación, vamos a crear nuevas fibras para todos los componentes que instancia con esta sintaxis JSX.

10. Renderizando el Proveedor de Contexto

Short description:

Renderizamos el proveedor, que es un proveedor de contexto y actualiza el valor del objeto de contexto en función de sus props.

Entonces, también renderizamos el proveedor al que le pasamos el último valor del nombre de usuario en las props y nuestro y hemos terminado con la aplicación. Así que podemos pasar al siguiente árbol de fibra, nuestro proveedor de contexto. ¿Deberíamos renderizar el proveedor? Bueno, no se marcó para renderizar, pero hay un segundo criterio para renderizarlo y se basa en el valor de las props. Vamos a comparar este objeto de props, el objeto de props del árbol de fibra nuevo con el del árbol anterior. Vamos a comparar estos dos objetos mediante igualdad superficial y si son iguales, no lo renderizamos, de lo contrario, sí. Y en nuestro caso, son diferentes. Así que renderizamos el proveedor. Así que ejecutamos este componente de función, pero eso no es todo. Verás, este componente es algo especial. No es solo un componente de función regular. Es un proveedor de contexto. Entonces, también hace otras cosas, como actualizar el valor del objeto de contexto, en función del valor que obtuvo de sus props. Así que el proveedor actualiza el valor del objeto de contexto y hemos terminado con el proveedor. Así que podemos pasar al siguiente árbol de fibra.

11. Renderizando Componentes y el Árbol de Fibra

Short description:

Cuando creamos una nueva fibra para los saludos, creamos un nuevo objeto para sus props. Aunque los objetos pueden parecer similares, tienen referencias diferentes. La igualdad superficial de JavaScript considera que los objetos vacíos no son iguales. Por lo tanto, renderizamos los saludos. Luego ejecutamos los componentes de función, leemos el último valor del nombre de usuario del objeto de contexto y creamos una nueva fibra para el párrafo. También se renderiza el párrafo y el botón. React compara el nuevo árbol con el anterior y aplica las diferencias al DOM. Es importante tener en cuenta que en realidad solo hay un árbol, pero es más fácil pensar en él como dos árboles. El árbol de fibra, no el código, es la fuente de verdad para saber qué componentes pueden haber cambiado y deben ser renderizados.

Saludos, ¿debemos renderizar los saludos? Bueno, no se marcó para renderizar, pero ¿han cambiado sus props? Bueno, en realidad sí. Ya sé, dos objetos vacíos, parecen muy similares, pero este es un objeto diferente. Así que cuando creamos una nueva fibra para los saludos, creamos un nuevo objeto para estas props también. Tiene la misma, no, una referencia diferente, si se me permite decirlo. Y en JavaScript, a través de la igualdad superficial, recuerda que el objeto vacío igual al objeto vacío es falso a través de la igualdad superficial. Así que en nuestro caso, estos dos objetos son diferentes y renderizamos los saludos.

Entonces ejecutamos estos componentes de función. Leemos el último valor del nombre de usuario del objeto de contexto y creamos una nueva fibra para el párrafo al que le pasamos el nuevo valor del nombre de usuario. Y hemos terminado con los saludos. Así que pasamos al párrafo, que se renderiza porque sus props han cambiado, solo tienen cuatro saludos. Y pasamos al botón, que también se renderiza. Y hemos terminado de construir nuestro árbol. Ahora, React va a comparar este nuevo árbol con el de la orden anterior y aplicar las diferencias al DOM. Y ahora hemos terminado. Esto fue algo mecánico. Así que retrocedamos un poco. Hay una o dos cosas que me gustaría discutir juntas. Primero sobre React y luego hablaremos sobre el contexto.

Sobre React, una pequeña aclaración. No es del todo cierto que tengamos estos dos árboles. En realidad, solo hay uno. Y cada fibra conserva toda su historia de estados. Pero me resulta más fácil pensar en ello como dos árboles. Y quiero decir, es mi modelo mental. Así que si quiero tener dos árboles, tendré dos árboles. Segunda cosa, aún sobre React. Hay una idea equivocada que tenía sobre React que quería compartir contigo. Solía pensar que la fuente de verdad, para saber qué componentes pueden haber cambiado y cuáles deben ser renderizados, era el código. Pero no lo es. El árbol de fibra lo es.

12. Understanding Rendering and Context Usage

Short description:

Cuando renderizamos la aplicación, se crea una nueva fibra para los saludos y se recorre todo el árbol. React renderiza los saludos cuando detecta que sus props han cambiado. En el uso cotidiano, los primeros componentes debajo del proveedor rara vez son consumidores de contexto. Se pueden agregar componentes adicionales entre el proveedor y el primer consumidor de contexto. Cuando se cambia el valor del contexto, se renderizan todos los componentes en cascada.

Solía pensar que cuando renderizamos la aplicación, el hecho de que estemos llamando a este componente de saludos de esta manera significaba que lo ejecutaríamos de inmediato. Pero eso no es lo que está sucediendo. Lo que sucede es que cuando renderizamos la aplicación, cuando ejecutamos esta línea, creamos una nueva fibra para los saludos. Y luego estamos recorriendo todo el árbol. Más adelante, cuando visitamos los saludos, React dice: 'oh, sus props han cambiado. Deberíamos renderizar eso'. Y solo entonces ejecutamos estas líneas. La fuente de verdad es el árbol de fibra.

Ahora, en tu vida diaria, sé que no estarás dibujando árboles de fibra. Entonces, lo que puedes recordar, lo que puedes llevar de esto es que cuando estás debajo, cuando el componente se renderiza, todos los componentes que se instancian también se renderizarán. Ahora, sobre los contextos. Así es como funcionan los contextos. Cambiamos el valor del estado que se refiere a los estados establecidos. Se renderiza el proveedor. Actualiza el valor del contexto, lo siento, problemas de animación. Actualiza el último valor de contexto, el valor del contexto de los objetos de contexto. Y luego todos estos componentes se renderizarán en cascada y este componente de gradiente leerá el último valor de contexto de los objetos de contexto. Pero en realidad, aún no hemos terminado. Esto no representa realmente el uso cotidiano del contexto. En la vida real, los primeros componentes ubicados justo debajo del proveedor rara vez son consumidores de contexto.

En la vida real, se ve más así. Agregamos algunos componentes adicionales entre el proveedor y el primer consumidor de contexto. En este caso, si observamos estos componentes A y B, ¿crees que también se renderizarán si cambiamos nuestro valor de contexto si hacemos clic en este botón? Bueno, en realidad sí. Si hacemos clic en este botón aquí, vamos a renderizar la aplicación. Entonces, cuando se ejecuta la aplicación, se crea una nueva fibra para A. Por lo tanto, A se renderizará. Entonces creará una nueva fibra para B. Por lo tanto, B se renderizará y así sucesivamente. Todos estos componentes se renderizan en cascada. Pero eso es una lástima.

13. Optimizando la Renderización del Contexto

Short description:

Queremos evitar renderizar componentes que no dependen del contexto cuando el valor del contexto cambia. Una forma de lograr esto es memoizando el primer componente debajo del proveedor. Otra forma es extraer el proveedor en su propio componente personalizado y pasar el resto del árbol como una propiedad children. Al hacer esto, cuando el valor del contexto cambia y se renderiza el proveedor, los componentes pasados como children no se volverán a renderizar. Demostremos esto cambiando el valor del contexto y observando el proceso de renderizado. Duplicamos el árbol de fibra, marcamos el componente que contiene el estado y recorremos el árbol. No volvemos a renderizar la aplicación porque sus props no han cambiado. Esta optimización nos permite evitar renders innecesarios y mejorar el rendimiento.

Hemos renderizado porque cambiamos el valor del contexto, pero A y B no dependen del contexto. No han cambiado. No deberíamos renderizarlos. Es una lástima. Y quiero decir que cuando llamas a useContext, intentas llamarlo lo más bajo posible en tu árbol, lo más cerca posible de donde realmente lo necesitas. Entonces, si podemos, sería bueno evitar renderizar todos los componentes ubicados entre el proveedor y el consumidor de contexto.

Entonces, ¿cómo podemos lograr esto? ¿Cómo podemos evitar volver a renderizar A y B si cambiamos nuestro valor de contexto? Bueno, una cosa que ya había escuchado antes es memoizar el primer componente ubicado justo debajo del proveedor. De esta manera, memoizamos este componente. De esta manera, detenemos la propagación del renderizado. Esto debería funcionar, pero en realidad, hay otra forma de lograr esto, que está aún más cerca de un uso real del contexto. ¿Puedes adivinar qué es? Es extraer tu proveedor en su propio componente personalizado y pasar el resto del árbol como una propiedad children. De esta manera, cuando cambiamos nuestro valor de contexto y se renderiza el proveedor de autenticación, este componente A que se pasa como children no se renderizará y detendremos la propagación del renderizado.

Hagamos la demostración rápidamente. Haga clic en este botón aquí y cambie nuestro valor de contexto. Duplicamos nuestro árbol de fibra, vamos a marcar el componente que contiene el estado como necesidad de renderizar. Esta vez no es la aplicación, es este componente de proveedor de autenticación personalizado. Marcamos el proveedor de autenticación y comenzamos a recorrer nuestro árbol. Comenzamos con la aplicación, ¿debemos renderizar la aplicación? Bueno, no se marcó para renderizar, pero ¿han cambiado sus props? En realidad, no. Esta vez, este objeto de props es el mismo que este. Cuando duplicamos nuestro árbol, este árbol es una copia superficial de este. Es una copia directa de este, por lo que este objeto de props es una copia directa de este. Mantienen la misma referencia, por así decirlo. En JavaScript, esta vez a través de la igualdad superficial, estos dos objetos son iguales. Entonces no volvemos a renderizar la aplicación. ¿Lo notaste? Es el primer componente en los últimos 10 minutos que en realidad no renderizamos. Se siente genial. Muy bien. Sigamos con el proveedor. Se renderiza como se marcó, así que lo ejecutamos. Obtenemos el último valor de nombre de usuario y creamos nuevas fibras para el proveedor y el botón.

14. Comprendiendo el Rol del Proveedor

Short description:

Pero aquí, children es solo una propiedad, solo una variable. El proveedor se encargará de asegurar que los consumidores de contexto se rendericen. AuthProvider, nuestro proveedor de contexto, marcará las lecturas como necesidad de renderizado. Extraer el proveedor en sus propios componentes personalizados no solo conduce a una mejor separación de responsabilidades, sino que también asegura que todos los componentes ubicados entre el proveedor y el primer consumidor de contexto no se rendericen. El rol del proveedor es absolutamente crucial. Se encargará tanto de actualizar el valor del objeto de contexto dentro de los objetos de contexto como de asegurar que los consumidores se rendericen.

Pero, ¿qué pasa con esta propiedad children? ¿Qué pasa con este componente A que se pasó como propiedad children? ¿Deberíamos crear una nueva fibra para él? Bueno, en realidad no. La razón por la que creamos una nueva fibra para un botón es debido a esta sintaxis JSX, que es equivalente a la función JSX que crea fibras. Pero aquí, children es solo una propiedad, solo una variable. No hay JSX aquí, por lo que no hay razón para crear una nueva fibra para A. Entonces, no hay una nueva fibra para A y hemos terminado con el proveedor. Podemos pasar al proveedor de contexto real, que se renderiza cuando sus propiedades han cambiado. Actualiza el valor del contexto y pasamos a A, que tampoco se vuelve a renderizar. Observa que, al igual que para la aplicación, este objeto de propiedades es el mismo que este, por lo que no renderizamos A, ni B, ni saludos. Pero ahora tenemos un problema.

Saludos es un consumidor de contexto. Queremos que se renderice para leer el último valor del nombre de usuario, de lo contrario, nuestra aplicación no tiene sentido. Queremos que se rendericen los saludos y, de hecho, lo harán. El proveedor se encargará de asegurarlo. Hay algo que no te dije. Volvamos atrás cuando visitamos el proveedor. Dijimos que cuando se renderizara el proveedor, actualizaría el valor del objeto de contexto, pero eso no es todo lo que hace. También se asegurará de que los consumidores de contexto se rendericen. Recorrerá todas las fibras que se encuentran debajo de él y marcará los consumidores de contexto como necesidad de renderizado. Tiene esta información dentro de las fibras porque cuando se renderiza un componente y usa un contexto, useContext escribirá esta dependencia hacia el contexto dentro de la fibra. Entonces, AuthProvider, nuestro proveedor de contexto, marcará las lecturas como necesidad de renderizado. De esta manera, incluso si un componente se memoiza en el medio y se detiene la propagación del renderizado, se asegura de que los consumidores se rendericen. Y puedes ver que no mentí. Este componente A no se renderizó cuando se renderizó AuthProvider porque se pasó como propiedad children. Entonces, de hecho, extraer el proveedor en sus propios componentes personalizados no solo conduce a una mejor separación de responsabilidades, sino que también asegura que todos los componentes ubicados entre el proveedor y el primer consumidor de contexto no se rendericen. Y esto es, en realidad, oh sí, lo siento, una última cosa. Una vez que se renderiza el primer consumidor de contexto, por supuesto, si agregas algunos componentes adicionales debajo de él, todos ellos también se renderizarán. Y esto es, en realidad, cómo funciona el contexto. Y puedes ver que el rol del proveedor es absolutamente crucial. Se encargará tanto de actualizar el valor del objeto de contexto dentro de los objetos de contexto como de asegurar que los consumidores se rendericen para que puedan leer el último valor de contexto de los objetos de contexto.

15. Uso Condicional de useContext en Hooks

Short description:

Con esta imagen completa de cómo funciona el contexto, podemos confirmar que useContext se puede usar condicionalmente sin interferir con otros hooks. Sin embargo, se recomienda no llamar a useContext condicionalmente para evitar confusiones, especialmente para desarrolladores inexpertos. Puede haber otros hooks además de useContext, como el hook use con Octobot, que también se pueden usar condicionalmente. ¡Gracias!

Con esta imagen completa de cómo funciona el contexto, podemos confirmar que de hecho, useContext se puede usar condicionalmente. No interfiere con otros hooks. Por eso se puede usar useContext de forma condicional. Y eso es todo lo que quería decirles sobre useContext, estos Curious Hooks.

¿Tengo un último minuto para hacer una advertencia? Tienes un último minuto para hacer una advertencia rápida, adelante. Gracias. Solo quería decir que no lo hagan. No llamen realmente a useContext de forma condicional. Es mejor para las desarrolladoras jóvenes mantenerlo de la misma manera que los demás para asegurarse de que no se pierdan.

Y también, una pregunta rápida. ¿Crees que puede haber otros hooks? ¿Es useContext el único? ¿Recuerdas el hook use con Octobot? Dijimos que podríamos usarlo de forma condicional. ¿Por qué es eso? Y sí. Muchas gracias. Aquí tienes algunos recursos si quieres seguir profundizando y construir tu propio modelo mental del comportamiento de renderizado de amenazas. Eso fue increíble. Dame algo.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Advanced Conference 2021React Advanced Conference 2021
27 min
(Easier) Interactive Data Visualization in React
Top Content
If you’re building a dashboard, analytics platform, or any web app where you need to give your users insight into their data, you need beautiful, custom, interactive data visualizations in your React app. But building visualizations hand with a low-level library like D3 can be a huge headache, involving lots of wheel-reinventing. In this talk, we’ll see how data viz development can get so much easier thanks to tools like Plot, a high-level dataviz library for quick & easy charting, and Observable, a reactive dataviz prototyping environment, both from the creator of D3. Through live coding examples we’ll explore how React refs let us delegate DOM manipulation for our data visualizations, and how Observable’s embedding functionality lets us easily repurpose community-built visualizations for our own data & use cases. By the end of this talk we’ll know how to get a beautiful, customized, interactive data visualization into our apps with a fraction of the time & effort!

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn