Manteniéndose seguro en un mundo concurrente

Rate this content
Bookmark

Con React 18, las esperadas características concurrentes ahora están disponibles para el público. Si bien técnicamente no introducen nuevas restricciones sobre cómo construimos nuestros componentes, hay muchos patrones que antes funcionaban pero que ahora podrían introducir errores sutiles en nuestras aplicaciones. Aprendamos nuevamente las reglas de React para poder mantenernos seguros en este nuevo mundo concurrente.

22 min
24 Oct, 2022

Video Summary and Transcription

Esta charla explora las implicaciones de las nuevas características concurrentes en React 18 y cómo afectan a los desarrolladores. Se discute la premisa fundamental de React y la importancia de los componentes de función pura. La charla también aborda conceptos erróneos sobre el proceso de renderizado de React y la prevención de desgarros en las aplicaciones. Además, se destacan las fases de reconciliación y confirmación en React y los desafíos de la gestión de dependencias en las bibliotecas de gestión de estado.

Available in English

1. Introducción a las características concurrentes de React 18

Short description:

Esta charla explora las implicaciones de las nuevas características concurrentes en React 18 y cómo afectan a los desarrolladores. El orador, Andreas, comparte su experiencia como líder de desarrollo en una agencia de software y destaca la importancia de mantenerse seguros en un mundo concurrente.

Espero que estén teniendo una conferencia increíble hasta ahora. Tal vez incluso hayan escuchado un par de charlas mencionando las nuevas características concurrentes que se lanzaron en React 18 hace un par de meses. En esta charla, no vamos a entrar en detalles sobre cómo funcionan estas características y qué hacen, pero queremos analizar las implicaciones y ramificaciones que esas características tienen en nosotros como desarrolladores para poder mantenernos seguros en un mundo concurrente de React.

Antes de adentrarnos en eso, permítanme contarles un poco sobre mí. Mi nombre es Andreas y soy de Dresden, Alemania, donde soy líder de desarrollo en una pequeña agencia de software. Nuestro trabajo consiste en ir a otras empresas de desarrollo de software y ayudar a los equipos a acelerar sus proyectos de software. Lo hacemos utilizando tecnologías como TypeScript React. Así que esto es exactamente lo que hago todos los días.

En este trabajo, lo que nos dimos cuenta en los últimos meses es que hay mucho miedo, incertidumbre y duda debido al nuevo lanzamiento de React y las nuevas reglas y lo que hay que hacer para estar seguro en el modo concurrente en sus aplicaciones. Y por eso propuse esta charla, para que puedan relajarse y mantenerse seguros en un mundo concurrente.

2. Evolución de las técnicas de renderizado de React

Short description:

Abramov introdujo el renderizado asíncrono en 2018 para que React se adapte al dispositivo del usuario y garantice interacciones rápidas y receptivas. Desde entonces, la fecha de lanzamiento se retrasó y el nombre cambió a renderizado concurrente o modo concurrente. Con React 18, se introdujeron características concurrentes que permiten a los desarrolladores optar por partes específicas de su aplicación. Las reglas de React no han cambiado, pero ahora las estamos utilizando de manera más efectiva.

Cuando retrocedemos un par de años, hasta 2018, Abramov introdujo el renderizado asíncrono. Por lo tanto, React debería adaptarse al dispositivo del usuario, las interacciones rápidas deberían sentirse instantáneas y las interacciones lentas deberían sentirse receptivas. La técnica principal consistía en dividir el proceso de renderizado para poder pausar, reanudar, realizar diferentes actualizaciones, de modo que nuestra aplicación se mantenga rápida y receptiva, sin importar el dispositivo o las condiciones de la red.

Desde entonces, muchas cosas han cambiado. Por ejemplo, la fecha de lanzamiento se ha retrasado un poco y el nombre ha cambiado de renderizado asíncrono a renderizado concurrente o modo concurrente. Y luego, con React 18, el equipo tomó la increíble decisión de no introducir un modo concurrente que cambie toda su aplicación a este nuevo mundo concurrente, sino que introdujo características concurrentes para que pueda optar por partes pequeñas de su aplicación en las características concurrentes, de modo que no toda su aplicación tenga que estar lista para el modo concurrente, sino solo partes de su aplicación.

Incluso lanzaron una publicación en el blog en ese momento, donde realizaron ciertos cambios en la API de React para preparar este cambio para el futuro. Eliminaron los métodos `componentWillMount`, `componentWillReceiveProps` y `componentWillUpdate`, o los reemplazaron por variantes inseguras. Esto es para que ustedes, como desarrolladores, sepan que estos métodos no son realmente seguros de usar con características concurrentes, pero aún pueden estar en su código siempre y cuando no utilicen las características concurrentes. Podría decirse que las reglas de React han cambiado desde entonces. Pero no es cierto. Las reglas de React no han cambiado desde entonces. Este es el punto más importante de mi presentación. Las reglas de React no han cambiado. Solo ahora estamos comenzando a aprovechar realmente las mismas reglas que estuvieron presentes desde hace mucho tiempo.

3. Premisa fundamental de React y capa de abstracción

Short description:

La premisa fundamental de React es que las interfaces de usuario son simplemente una producción de datos en una forma diferente de datos. La misma entrada siempre produce la misma salida. Las funciones de renderizado y los componentes de clase ahora se han convertido en componentes de función, pero la regla sigue siendo la misma: deben ser puros. No deben leer valores del mundo exterior ni modificarlo. React se encarga de decidir cuándo ocurre el renderizado y qué parte de la aplicación se renderiza, lo que permite a los desarrolladores trabajar por encima de esta capa de abstracción.

Encontré este documento de diseño que establece los conceptos y los modelos mentales alrededor de React hace 7 años. Y en esto dice que la premisa fundamental de React es que las interfaces de usuario son simplemente una producción de datos en una forma diferente de datos. La misma entrada siempre produce la misma salida. Una función pura. Entonces, lo que eran las funciones de renderizado y nuestros componentes de clase en ese entonces ahora son componentes de función. Pero la regla sigue siendo la misma. Estas funciones, la función de renderizado y nuestras funciones de componente deben ser puras. No deben leer valores del mundo exterior. Por ejemplo, no deben usar math.random y no deben modificar el mundo exterior. Por lo tanto, agregar algunos event listeners, obtener algunos datos del servidor, porque React quiere tomar la decisión de cuándo ocurre el renderizado y qué parte de nuestra aplicación se renderiza. Nosotros, como desarrolladores, solo debemos vivir por encima de este nivel de abstracción para no interferir con todo lo que está por debajo de esta capa de abstracción.

4. Malentendidos sobre el Proceso de Renderizado de React

Short description:

La fase de reconciliación en el proceso de renderizado de React no es atómica, a diferencia de un malentendido común. En versiones anteriores de React, el reconciliador de pila hacía que el proceso de renderizado no fuera interrumpible. Sin embargo, con la introducción de la arquitectura Fiber en React 16 y las características concurrentes en React 18, el proceso de renderizado ahora se puede dividir. Esto permite que React ceda al bucle de eventos del navegador y maneje las entradas del usuario durante el proceso de renderizado.

Esto nos lleva a un par de malentendidos sobre este proceso de renderizado que simplemente asumimos que eran ciertos pero que nunca son realmente ciertos y no son ciertos hoy en día con las características concurrentes. El primer malentendido es que la fase de reconciliación es atómica. Entonces, el proceso de renderizado de React, como quizás sepas, se divide en esas dos partes, la fase de reconciliación donde React llama a todas tus funciones o tus componentes, genera el JSX, compara el JSX con la versión anterior para luego generar esas unidades de trabajo que se realizarán más tarde. Y esta parte posterior es la fase de confirmación.

Entonces, cuando todo se ha reconciliado, React sabe qué se debe hacer para que la interfaz de usuario coincida con el estado actual del mundo. Luego se ejecuta la fase de confirmación y React actualiza la interfaz de usuario, sin importar si es el DOM, React Native o la terminal o cualquier otra cosa. En este primer malentendido que tenemos en mente, vemos la reconciliación como un proceso atómico. Cuando comienza el renderizado, se ejecuta hasta el final. Esto era cierto en versiones anteriores de React, pero nunca se garantizó. Nunca fue una regla de React, simplemente sucedía que era cierto debido a los detalles de implementación.

En ese entonces, React utilizaba el llamado reconciliador de pila. Teníamos esta pila donde la biblioteca de React recorría nuestra aplicación hasta niveles inferiores, llamaba a la función de la aplicación, llamaba a la función principal, etc. Y el problema con ese proceso era que simplemente no era interrumpible. No era posible interrumpir esta fase de reconciliación. Por eso hicieron esta importante reestructuración con React 16, donde cambiaron a la arquitectura Fiber. ¿Qué significa esto? React ya no tiene la pila de componentes, sino que es una simple lista por la que podemos iterar linealmente para realizar el trabajo requerido para cada componente.

Y lo genial ahora con las características concurrentes es que ahora la fase concurrente, todo lo que hace React, también se puede dividir, si queremos eso como usuarios. Eso significa que el bucle de eventos, mientras tanto, tiene un poco de espacio para manejar algunas entradas del usuario. Por ejemplo, el usuario desplazó la página o hizo clic en el botón o ingresó algunos valores en un formulario. El bucle de eventos ahora puede procesar esos cambios porque React ahora puede ser interrumpido. React verifica después de cada componente, ¿todavía tengo tiempo o hay algún trabajo por hacer desde el navegador? Y luego cede al navegador para que el navegador pueda manejar este trabajo.

Debido a que esto es un poco difícil de entender, hice una pequeña demostración para eso. Lo que tenemos aquí es una pequeña aplicación donde a la izquierda tenemos esos tres componentes y en la parte superior tenemos algunos controles para que podamos controlar lo que sucede dentro de nuestra aplicación. A la derecha tengo la consola abierta, donde puedes ver que todos los componentes registran en la consola cuando comienzan a renderizarse y cuando terminan de renderizarse. Borremos eso y ejecutemos un nuevo renderizado. El primer componente comienza a renderizarse, luego termina. Después de eso, comienza el segundo componente y luego directamente después de eso comienza el tercer componente. Como tal vez puedas ver, cada componente tarda aproximadamente 5 segundos en hacer su trabajo. Este es un retraso artificial para que podamos observar más de cerca lo que está sucediendo aquí. Pero por defecto, este proceso de renderizado sigue siendo atómico.

5. Reconciliación de React y Prevención de Desgarros

Short description:

Cuando se vuelve a renderizar un componente de React, el proceso de reconciliación toma una instantánea de los elementos JSX y los confirma en el DOM después de completar la reconciliación. Las actualizaciones de baja prioridad permiten que React ceda al navegador y maneje los clics de eventos antes de continuar con el renderizado. Sin embargo, este comportamiento no determinista puede provocar desgarros en la aplicación, donde diferentes componentes muestran instantáneas diferentes del estado. Para evitar esto, es importante evitar leer valores que puedan cambiar fuera del mundo de React, como variables globales o almacenamiento local. Además, se debe tener precaución al usar soluciones personalizadas de gestión de estado como Redux, ya que acceder al estado durante el renderizado puede causar problemas similares.

Cuando hago clic en el botón de volver a renderizar, cambia este valor de estado global. Simplemente sigo haciendo clic hasta que todo termine con el renderizado. Puedes ver que React renderizó nuestro componente con el estado inicial y solo después de este proceso de reconciliación manejó mis eventos e incrementó el estado global, que es simplemente una variable global dentro de mi aplicación. También puedes ver que el estado en nuestro componente, en la interfaz de usuario, todavía representa el estado desde el inicio del proceso.

Durante esta reconciliación, React toma una instantánea dentro de esos elementos JSX y luego, cuando termina, confirma esas instantáneas en el DOM. Entonces, sin importar cuál sea el valor actual, confirma la instantánea desde el momento en que se ejecutó la reconciliación.

Ahora cambiemos a la actualización de baja prioridad. Está utilizando react-use-start-transition, como quizás ya hayas visto en otras charlas, para programar una actualización de baja prioridad. Ahora hagamos clic en volver a renderizar de baja prioridad y luego en cambiar el estado global nuevamente. Como quizás hayas visto, después de que el primer componente termine de renderizarse, React lo cede al navegador y el navegador decide que ahora necesita manejar esos clics de eventos. Llama a mi función que simplemente registra en la consola y cambia el valor de la variable, luego vuelve al navegador al bucle de eventos y el bucle de eventos decide que ahora React vuelve a tomar el control y continúa con el renderizado.

Esto sucede entre cada componente durante el proceso de renderizado, pero como ya puedes ver entre el componente 2 y 3, el bucle de eventos decide nuevamente darle a React la opción de hacer algo y no al controlador de eventos. Entonces, es un poco no determinista lo que está haciendo el navegador en segundo plano. A veces, los registros de la consola también aparecerían entre estos dos o solo aquí. Pero como puedes ver en nuestro caso, entre el componente 1 y 2, ocurrió el cambio en la variable. El primer componente se renderizó con el estado 25, el segundo se renderizó con 28 y el tercero también se renderizó con 28. Entonces, ahora puedes ver que el proceso de reconciliación ya no es estrictamente atómico en una aplicación moderna de React porque no sabemos si alguien más arriba en el árbol está utilizando esas características concurrentes y nos presenta esas fases de reconciliación que se dividen en el tiempo.

Y como puedes ver, esto conduce a problemas. Nuestro primer componente muestra el 25 y el segundo y tercer componente muestran el 28. Ahora tenemos este desgarro en nuestra aplicación. Una parte de nuestra aplicación muestra una instantánea en un momento determinado y las otras partes de la aplicación muestran otra instantánea en un momento determinado. Esto, por supuesto, no es lo que queremos.

Entonces, eso significa que necesitamos hacer para evitar este desgarro desagradable dentro de nuestras aplicaciones. Necesitamos dejar de leer valores que podrían cambiar fuera del mundo de React. En nuestro caso, esto era una simple variable global y leímos el valor de la variable y lo cambiamos en algún controlador de eventos. Si eso fuera una constante, estaría totalmente bien porque una constante nunca puede cambiar y luego podemos usar esa constante durante el renderizado. Pero necesitamos dejar de leer valores que podrían cambiar fuera de React. Por ejemplo, una variable local o almacenamiento local porque cualquiera puede escribir en el almacenamiento local o el valor actual de una propiedad de referencia porque esas referencias se hacen explícitamente para que tengas objetos que puedas mutar y restablecer fuera del mundo de React sin que React sepa que algo ha cambiado. Entonces, React no sabe que necesita volver a renderizar, no sabe que necesita abortar este nuevo proceso de renderizado concurrente y mostrará un estado inconsistente en tus interfaces de usuario en los peores casos. Y esto también significa que estás escribiendo tu propio Redux y líneas de moda, por ejemplo, que debes tener mucho cuidado de cómo lo conectas a tus componentes porque si simplemente llamas a getState() durante el proceso de renderizado, es el mismo problema.

6. Fases de Reconciliación y Commit de React

Short description:

Leer variables globales que pueden cambiar puede llevar a problemas de desgarro. Las fases de reconciliación y commit de React garantizan la atomicidad, incluso con características concurrentes. Sin embargo, el modo estricto de React en desarrollo detecta inconsistencias entre las fases de reconciliación. Las características concurrentes introducen divisiones entre los pasos de reconciliación, lo que potencialmente vuelve obsoleta la fase de commit o cambia su resultado. En la aplicación de demostración, mostrar y ocultar bloques con actualizaciones de alta y baja prioridad demuestran las fases de renderizado y commit.

Exactamente lo mismo que leer alguna variable global que puede cambiar, de modo que también puedes encontrarte con esos problemas de desgarro. La mayoría de las veces agregarás otro escucha de eventos, por ejemplo, para los cambios en el almacenamiento o para cambios en algún almacenamiento local, por ejemplo. Entonces, todo funcionará eventualmente, pero puede haber ciertos períodos de tiempo en los que tu aplicación muestre este estado desgarrado.

Antes de entrar en cómo puedes resolver estos problemas, veamos primero el segundo concepto erróneo. Una renderización o una fase de reconciliación siempre conduce a exactamente una fase de commit. Por defecto, esto puede ser cierto. Tenemos este proceso de reconciliación que recorre todos nuestros componentes dentro de nuestra aplicación y luego, cuando esto se completa y reconocemos lo que se debe hacer, cambiará a la fase de commit y ejecutará el commit y actualizará el DOM para todos nuestros componentes. Incluso cuando estamos utilizando características concurrentes, aún tenemos la garantía de que la fase de commit es atómica. Incluso si tenemos divisiones de tiempo en la fase de reconciliación, tenemos la garantía de que el commit es atómico porque el equipo de React tomó la decisión de que no quieren mostrar datos inconsistentes. Entonces, dicen que cuando comenzamos a actualizar el DOM, hacemos todo lo que actualmente tenemos que hacer para actualizar cada lugar que lee el estado para que todo esté en un estado consistente.

Pero ahora, hay algunas situaciones en las que la correspondencia uno a uno entre la reconciliación y la fase de commit ya no es cierta. Cuando estás utilizando el modo estricto de React en desarrollo, por ejemplo, ya tienes este cambio en el que la fase de reconciliación se ejecutará dos veces y la fase de commit solo se ejecutará una vez. Esto ya te advierte en desarrollo cuando esas dos fases de reconciliación producen resultados diferentes. Porque, como dijimos antes, cuando la entrada es la misma, la salida siempre debería ser la misma. Entonces, el modo estricto te ayuda a detectar cuando estás utilizando valores externos que podrían cambiar fuera de React. Por ejemplo, cuando estás utilizando math.random, React detectará que las diferentes fases de reconciliación producen resultados diferentes y te advertirá. Pero ahora, con esas características concurrentes, tenemos esas divisiones entre los pasos de reconciliación. Entre cada uno de esos pasos, algo podría suceder que podría hacer que la fase de commit sea obsoleta o cambiar el resultado de la fase de commit porque algún estado cambió nuevamente.

Podemos ver eso en nuestra aplicación de demostración nuevamente. Primero ocultemos nuestros bloques y marquemos la casilla Mostrar Commits, y limpiemos la consola. Ahora, mostremos nuestros bloques con una actualización de alta prioridad y luego, directamente después de eso, los ocultamos nuevamente. Después de eso, hago clic en Ocultar Bloques. Tenemos que esperar a que todos nuestros componentes se rendericen, uno, dos, tres, cinco segundos cada uno. Luego podemos ver que después de ese proceso, cuando se completa el renderizado, obtenemos esos commits para cada componente y directamente después de eso obtenemos esos desmontajes. Por defecto, tienes esta garantía de que estás renderizando y cuando terminas con la reconciliación, tus efectos se llamarán en la fase de commit y se llamarán los desmontajes porque nuestros elementos se ocultan directamente nuevamente. Ahora intentemos lo mismo con una actualización de baja prioridad. Mostramos los bloques con una baja prioridad y directamente después de eso ocultamos los bloques. Lo que podemos ver es que React renderizó nuestro primer bloque, el primer componente. Después de eso, cedió al navegador. El navegador manejó nuestro evento.

7. Renderizado de React y Renderizado Puro

Short description:

En el renderizado concurrente, si se cancela una actualización de baja prioridad, no se llaman efectos ni efectos de diseño. Esto puede llevar a problemas, por lo que los desarrolladores deben evitar suscribirse o mutar el mundo exterior dentro de los componentes. El renderizado debe ser puro para asegurar que no se necesite limpieza.

El evento establece la variable 'show', el interruptor 'show' vuelve a falso y React sabe que está bien, este es el estado antiguo que todavía tengo disponible aquí en mi construcción de renderizado concurrente. Por lo tanto, podemos cancelar esta nueva actualización de baja prioridad y mantener todo como está. Ahora tenemos este estado en el que se renderizó un componente, se llamó a nuestra función, pero no se realizó ningún commit. Por lo tanto, no se llamaron efectos ni efectos de diseño. Solo la fase de renderizado. Y esto, por supuesto, puede llevar a problemas. Y significa que nosotros, como desarrolladores, debemos dejar de suscribirnos o mutar el mundo exterior dentro de nuestros componentes. Porque cada vez que mutamos algo del mundo exterior o agregamos un escucha de eventos, por ejemplo, en una suscripción, entonces dependemos del hecho de que el usuario se desinscriba para limpiar después de nosotros. Pero en aquellos casos en los que solo tienes esta fase de reconciliación que se cancela por completo, nunca tendrás una fase de limpieza. Porque una función pura no necesita limpieza. Simplemente no la vuelves a llamar. Así que tenemos que asegurarnos de que nuestro renderizado en sí mismo sea puro nuevamente.

8. Problemas de dependencia en las bibliotecas de gestión de estado

Short description:

En las bibliotecas de gestión de estado, la adición automática de dependencias a los componentes durante la fase de reconciliación puede generar problemas. Esto es más común en las bibliotecas que en el código de la aplicación. Implica agregar variables como dependencias a un contenedor global de gestión de estado, lo cual puede causar problemas cuando no hay garantía de una fase de confirmación. Las aplicaciones de React típicamente no presentan este tipo de patrones.

La buena noticia es que esto ocurre muy raramente en el código de la aplicación que hemos visto ahí afuera. Pero esto ocurre con bastante frecuencia en las bibliotecas de gestión de estado. Algunas bibliotecas intentan determinar automáticamente qué variables estabas usando durante la fase de reconciliación y agregar esas variables como dependencias a este componente en algún contenedor global de gestión de estado. El componente se renderiza y reconoce que estás leyendo algunos valores y los registra como una dependencia. Esto podría verse algo así. Tenemos esta referencia para este escucha y cada vez que se ejecuta el componente, verificamos si ya hemos instanciado ese escucha y, si no, simplemente creamos una nueva función y la colocamos dentro del arreglo de escuchas de eventos en el objeto window. El objeto window es, por supuesto, un objeto global y agregamos una función, por lo que mutamos la lista de escuchas de eventos y agregamos una función en este objeto global. Podríamos hacer eso cuando estemos absolutamente seguros de que useEffectCleanup() limpiará la función del escucha nuevamente. Esto eliminará el mismo escucha de eventos que agregamos anteriormente. Pero como acabas de ver, ya no tenemos esta garantía o nunca tuvimos esta garantía de que después de cada proceso de renderizado definitivamente habrá una fase de confirmación, lo que significa que no debemos hacer esto en nuestras aplicaciones. Nuevamente, esto se aplica más a los mantenedores de bibliotecas y a los autores de bibliotecas, ya que en las aplicaciones normales de React rara vez se ven patrones como este. Ahora pasemos a las tres soluciones para estos problemas. La primera solución es simplemente hacer toda la comunicación con el mundo exterior dentro de UseFX. Sé que hay algunos miembros de la comunidad que podrían matarme por decir eso, pero UseFX está hecho para eso, por lo que puedes sincronizar el mundo de React con el mundo exterior en UseFX, puedes iniciar solicitudes de red, puedes iniciar suscripciones, puedes agregar valores del mundo exterior dentro de UseFX, totalmente bien. El principal problema con eso es, en el contexto de la gestión de estado, por ejemplo, en el primer proceso de renderizado, aún no tienes el valor listo. Solo cuando renderizas una vez, confirmas una vez, muestras el valor inicial, pero no lo tienes del almacenamiento. Solo dentro de UseFX estás haciendo esa conexión con la biblioteca de gestión de estado, obteniendo el valor, colocándolo en el estado y volviendo a renderizar. Eso significa que funciona bastante bien para cosas asíncronas, pero para cosas sincrónicas es bastante engorroso, porque siempre conduce a este doble renderizado. La segunda opción es simplemente elegir una biblioteca que se haya hecho para tu caso de uso. La mayoría de las bibliotecas modernas de gestión de estado ya están preparadas para el modo concurrente, porque el equipo ha estado trabajando muy de cerca con los mantenedores de bibliotecas populares. Algo como ReduxToolkit o ReactQuery ya están preparados, por lo que puedes usarlos sin preocuparte por esos problemas de desgarro con las características concurrentes. La tercera solución, cuando realmente quieres crear tu propia solución, es usar el gancho incorporado useSyncExternalStore. Esto se hizo específicamente para hacer una conexión para sincronizar el valor desde un almacenamiento externo con el mundo de React. Para hacer eso, primero definimos una función de suscripción. En nuestro caso, nos interesa el tamaño actual del objeto window, por lo que nos registramos en el evento de cambio de tamaño. Cada vez que se llama a resize, el navegador llama a la función de cambio de tamaño, se llama a alguna devolución de llamada desde dentro de nuestra función de suscripción. Simplemente devolvemos una función de limpieza que luego eliminará esta devolución de llamada nuevamente del objeto global. Ahora podemos tomar esta función de suscripción y pasarla como primer argumento a useSyncExternalStore. Así que simplemente le damos a React la decisión de cuándo queremos suscribirnos. Decimos, React, maneja la suscripción y cada vez que alguno de los eventos cambie, cada vez que algo cambie, llama a mi función de selector, que es el segundo argumento de useSyncExternalStore. Cada vez que se dispara el evento de cambio de tamaño, nuestra función extrae el innerWidth del objeto window y lo devuelve desde nuestro gancho. Eso significa que dentro de nuestro componente, podemos usar este ancho y usarlo directamente dentro del renderizado inicial y obtener actualizaciones de los renderizados en el futuro, sin tener problemas con el desgarro. Eso significa que podemos volver a confiar en la abstracción que React proporciona, porque React no quiere que nos preguntemos cuándo se llaman nuestras funciones. Solo quiere definir nuestras funciones de una manera pura, por lo que tenemos que definir funciones puras que no se comuniquen con el mundo exterior, solo a través de esos ganchos definidos. Y luego, como resultado, puedes estar seguro en un mundo concurrente. Gracias por escuchar.

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 Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
React Advanced Conference 2022React Advanced Conference 2022
29 min
Understanding React’s Fiber Architecture
Top Content
We've heard a lot about React's Fiber Architecture, but it feels like few of us understand it in depth (or have the time to). In this talk, Tejas will go over his best attempt at understanding Fiber (reviewed by other experts), and present it in an 'explain-like-I'm-five years old' way.
React Summit 2022React Summit 2022
27 min
Inside Fiber: the in-depth overview you wanted a TLDR for
I want to provide an in-depth overview of the important concepts behind reconciliation. We'll then explore how React uses the algorithm and go through a few magic words we hear a lot, like coroutines, continuations, fibers, generators, algebraic effects and see how they all relate to React.js.
React Summit 2023React Summit 2023
26 min
Server Components: The Epic Tale of Rendering UX
Server components, introduced in React v18 end these shortcomings, enabling rendering React components fully on the server, into an intermediate abstraction format without needing to add to the JavaScript bundle. This talk aims to cover the following points:1. A fun story of how we needed CSR and how SSR started to take its place2. What are server components and what benefits did they bring like 0 javascript bundle size3. Demo of a simple app using client-side rendering, SSR, and server components and analyzing the performance gains and understanding when to use what4. My take on how rendering UI will change with this approach
React Advanced Conference 2021React Advanced Conference 2021
30 min
Cracking the Concurrent Mode
With concurrent mode coming in React 18, let's talk about the complexities behind providing declarative APIs for concurrent rendering. While implementing concurrent mode APIs from scratch for Brahmos.js, I came across lot of use cases and variability which made it one of the most interesting problem to solve, and appreciate more the React's effort on advocating Concurrent UI. In this talk we will see what concurrent mode means for a web app, what are the internal complexities and how I solved it for Brahmos.js.
React Advanced Conference 2023React Advanced Conference 2023
28 min
A Practical Guide for Migrating to Server Components
Server Components are the hot new thing, but so far much of the discourse around them has been abstract. Let's change that. This talk will focus on the practical side of things, providing a roadmap to navigate the migration journey. Starting from an app using the older Next.js pages router and React Query, we’ll break this journey down into a set of actionable, incremental steps, stopping only when we have something shippable that’s clearly superior to what we began with. We’ll also discuss next steps and strategies for gradually embracing more aspects of this transformative paradigm.

Workshops on related topic

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 2020React Summit 2020
125 min
Getting Started with Suspense and Concurrent Rendering in React
Featured Workshop
React keeps on evolving and making hard things easier for the average developer.
One case, where React was not particularly hard but very repetitive, is working with AJAX request. There is always the trinity of loading, success and possible error states that had to be handled each time. But no more as the `<Suspense />` component makes life much easier.
Another case is performance of larger and complex applications. Usually React is fast enough but with a large application rendering components can conflict with user interactions. Concurrent rendering will, mostly automatically, take care of this.
You will learn all about using <Suspense />, showing loading indicators and handling errors. You will see how easy it is to get started with concurrent rendering. You will make suspense even more capable combining it with concurrent rendering, the `useTransition()` hook and the <SuspenseList /> component.