Manteniéndose seguro en un mundo concurrente

This ad is not shown to multipass and full ticket holders
React Summit US
React Summit US 2025
November 18 - 21, 2025
New York, US & Online
The biggest React conference in the US
Learn More
In partnership with Focus Reactive
Upcoming event
React Summit US 2025
React Summit US 2025
November 18 - 21, 2025. New York, US & Online
Learn more
Bookmark
Slides
Rate this content

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 de nuevo las reglas de React para poder mantenernos seguros en este nuevo mundo concurrente.

This talk has been presented at React Day Berlin 2022, check out the latest edition of this React Conference.

FAQ

Las características concurrentes en React permiten que los desarrolladores tengan el control total de cuándo se utiliza el nuevo comportamiento de React en su aplicación. Estas características permiten actualizaciones de baja prioridad y pueden interrumpir la fase de reconciliación, lo que significa que React puede pausar este proceso para manejar otros eventos del navegador.

Desde la introducción del renderizado asíncrono, ahora conocido como modo concurrente, React ha evolucionado para permitir a los desarrolladores controlar mejor el comportamiento de la aplicación sin optar por todo en este nuevo modo. Se han hecho adaptaciones en los métodos del ciclo de vida y se ha cambiado la garantía de que la fase de reconciliación sea atómica.

Al no usar características concurrentes, los desarrolladores pueden enfrentar problemas con aplicaciones que no manejan bien las actualizaciones de estado que ocurren durante las interrupciones de la fase de reconciliación, lo que puede llevar a inconsistencias en la interfaz de usuario o errores en la aplicación.

Se recomienda mover las interacciones que involucran efectos secundarios, como llamadas a APIs o suscripciones, dentro del hook useEffect. Esto asegura que las operaciones se manejen correctamente con un proceso de limpieza y no afecten la consistencia del estado de la aplicación durante las renderizaciones.

Para garantizar un manejo adecuado del modo concurrente, se debería utilizar useState o useReducer para manejar estados que puedan cambiar, evitar leer directamente de variables globales mutables durante la reconciliación, y considerar el uso de bibliotecas que estén diseñadas para ser seguras en un contexto concurrente como React Query o Redux Toolkit.

Andreas Roth
Andreas Roth
30 min
02 Dec, 2022

Comments

Sign in or register to post your comment.
Video Summary and Transcription
La charla discute las ramificaciones de las nuevas características concurrentes en React y los conceptos erróneos en torno al modelo de renderizado. Explora los cambios en el proceso de renderizado y la necesidad de manejar el estado cuidadosamente. También destaca los desafíos en la gestión de la comunicación con el mundo exterior y las bibliotecas recomendadas para la sincronización. Menciona los beneficios de usar el modo concurrente en frameworks existentes y las dificultades en la construcción de demos y la aplicación de la inmutabilidad. Por último, enfatiza los beneficios del modo concurrente para componentes pesados.

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

Short description:

Hola a todos. En esta charla, quiero hablar sobre las ramificaciones e implicaciones de las nuevas características concurrentes en React. También me presentaré y explicaré los dos grupos de desarrolladores con los que nos hemos encontrado. Retrocederemos unos años para comprender la visión de React y cómo ha evolucionado. Las reglas de React no han cambiado.

♪♪ Hola a todos. Espero que estén teniendo una conferencia increíble hasta ahora. Tal vez hayan escuchado algunas charlas o visitado algunos talleres o hayan tenido algunas discusiones sobre las nuevas características concurrentes que se lanzaron en la última versión de React.

En esta charla, quiero hablar sobre exactamente esas características, pero no quiero mostrar las API concretas, sino más bien centrarme en las ramificaciones e implicaciones que esas características tienen en ustedes como desarrolladores de aplicaciones.

Antes de adentrarnos en eso, me gustaría presentarme primero. Mi nombre es Andreas y soy líder de desarrollo en una pequeña agencia en Dresden y nuestro trabajo básicamente consiste en ingresar a los proyectos de otros equipos y ayudarles a mejorar su código, hacer que su software funcione mejor, acelerar su proceso de desarrollo. En este proceso, hablamos con muchos y muchos desarrolladores de diferentes equipos y nos dimos cuenta de que hay más o menos dos grupos de desarrolladores. Un grupo aún no ha oído hablar de las características concurrentes y está haciendo algo incorrecto en la aplicación que podría romperse cuando usen características concurrentes. El otro grupo no está utilizando características concurrentes porque temen que algo pueda romperse en sus aplicaciones. Entonces, muchos de ellos todavía no las están usando realmente.

Y es por eso que hoy quiero contarles un poco sobre esas nuevas características para asegurarme de que puedan mantenerse seguros en un mundo concurrente. Para comenzar, primero tenemos que retroceder unos años cuando Dan Abramov reveló la nueva visión de React. En ese entonces, esta característica todavía se llamaba renderizado asíncrono. El objetivo era adaptarse a la red del usuario y al dispositivo del usuario, para que incluso en dispositivos más pequeños, la aplicación aún pudiera sentirse receptiva. Y cuando el dispositivo es lo suficientemente rápido, todo sucede al instante sin tener ningún tiempo de espera superfluo que no necesiten en sus aplicaciones.

Desde entonces, mucho ha cambiado. Por ejemplo, la fecha de lanzamiento. Como saben, no estamos en 2018 en este momento, así que tuvimos que esperar unos años más. Y muchos otros temas también cambiaron. Por ejemplo, el nombre. En ese entonces, se presentó como renderizado asíncrono o async React. Luego se renombró un poco a modo concurrente o concurrent React, y luego el equipo tomó la increíble decisión de eliminar el modo para que no tengan que optar por toda su aplicación en este nuevo mundo. Pero lanzaron características concurrentes para que ustedes como desarrolladores tengan el control total de cuándo se utiliza el nuevo comportamiento de React en su aplicación y cuándo no.

En ese entonces, incluso lanzaron este artículo de blog donde hicieron algunas preparaciones para esta nueva característica. Por ejemplo, cambiaron el nombre de algunos de los métodos del ciclo de vida como component will mount, component will update, porque ya sabían que estas funciones no eran seguras para el modo concurrente. Tuvieron que hacer ciertas adaptaciones porque sabían a dónde iban, conocían su visión. Así que podrían decir en cierto sentido que React ha cambiado. Pero esto no es cierto. Este es el punto más importante de mi presentación hoy. Las reglas de React no han cambiado.

2. Reglas fundamentales de React y conceptos erróneos

Short description:

Las reglas fundamentales de React no han cambiado desde 2016. Ahora podemos comenzar a aprovechar estas reglas para mejorar nuestras aplicaciones. Sin embargo, ha habido conceptos erróneos en torno al modelo de renderizado de React, especialmente en lo que respecta a la atomicidad de la fase de reconciliación. En la arquitectura anterior, se garantizaba que la fase de reconciliación fuera atómica. Pero con el lanzamiento de React 16 y la introducción de la arquitectura de fibra, ahora la fase de reconciliación puede interrumpirse. Confiar en la atomicidad de la fase de reconciliación era confiar en detalles de implementación, lo que puede generar problemas.

Las premisas fundamentales y las reglas fundamentales a las que debemos adherirnos como desarrolladores siguen siendo las mismas que en 2016. Por lo tanto, las reglas de React no han cambiado. Recién ahora comenzamos a aprovecharlas realmente. Durante todos estos años, tuvimos que adherirnos a algunos conceptos básicos como la pureza y la ausencia de efectos secundarios sin obtener beneficios reales. Pero ahora, el framework comienza a utilizar realmente el hecho de que cumplimos con estas reglas para mejorar nuestras aplicaciones.

Esto se puede ver en este documento de diseño. Es de hace más de siete años. Aquí se establece que la premisa fundamental de la biblioteca React es que React en sí mismo es una proyección que toma datos como entrada y los transforma en una salida para que su aplicación sea una función pura simple. Con la misma entrada, siempre debería producir la misma salida. Pero como React no utilizaba realmente estas reglas en la aplicación, se han desarrollado algunos conceptos erróneos en torno al modelo de renderizado de React. El primero de ellos es que la fase de reconciliación de React es atómica.

Permítanme explicar qué significa la reconciliación. Cuando React se actualiza, ocurren dos fases. En primer lugar, está la fase de reconciliación. React llama a sus componentes de función, genera esos elementos JSX, los reúne todos juntos y los compara con la versión anterior. Esto es lo que se conoce coloquialmente como DOM virtual. Luego, en la segunda fase, la fase de confirmación, React toma todas esas diferencias y las aplica al DOM real que vemos como usuarios en el navegador. En la arquitectura anterior, se garantizaba que la fase de reconciliación siempre fuera atómica porque se implementaba de esa manera.

En ese entonces, teníamos el reconciliador de pila, lo que significa que React recorría su aplicación, pasaba por sus componentes, comenzaba con el componente de la aplicación y luego el componente de la aplicación renderizaba el componente principal, por lo que el reconciliador pasaba a este componente principal. Teníamos esta pila dentro de la biblioteca React que recorría su aplicación de manera ininterrumpible. Por lo tanto, cuando React comenzaba a trabajar en su componente de la aplicación, solo podía hacer otra cosa una vez que todo lo demás estuviera terminado. Con el lanzamiento de React 16, React cambió esta arquitectura a la arquitectura de fibra. Ya no tenemos esta pila de componentes dentro de nuestra aplicación, pero React mantiene internamente una lista de componentes y puede recorrer esta lista de manera iterativa e incluso interrumpir este proceso. Esto significa que mientras tanto, el grupo de eventos y el navegador tienen cierto margen para manejar eventos de usuario. Por ejemplo, el usuario se desplaza, pero React está realizando algunos cálculos. React puede pausarlos, manejar el evento del usuario, actualizar la interfaz de usuario o hacer algo más, enviar algunas solicitudes o algo similar, pero la fase de reconciliación ahora puede interrumpirse y no ocurrirá de manera atómica. Es muy importante tener en cuenta que nunca se garantizó que la fase de reconciliación fuera atómica. Simplemente sucedió de esa manera debido a la implementación. Confiar en eso significaba confiar en detalles de implementación que ahora generan problemas. Y para eso tengo una pequeña aplicación de demostración.

3. Cambios en el Proceso de Renderizado y Manejo del Estado

Short description:

Entonces, en esta aplicación de React, el proceso de renderizado se ralentiza artificialmente y la fase de reconciliación ya no es atómica debido a las características concurrentes introducidas en React 18. Esto puede provocar un efecto de desgarro donde diferentes componentes muestran diferentes versiones del estado. Para solucionar esto, debemos dejar de leer valores que pueden cambiar fuera del mundo de React, como variables globales, y en su lugar usar hooks como useState o useReducer. También se deben usar refs para objetos que pueden mutar alrededor de React sin desencadenar una reacción.

Entonces, limpiemos la consola ahora mismo. Lo que tenemos aquí es una aplicación simple de React donde tenemos tres bloques que muestran algún estado. Cada vez que hago clic en este botón de volver a renderizar, se actualiza algún estado y puedes ver en la consola que el renderizado se ralentiza artificialmente. Cada componente tarda aproximadamente cinco segundos en realizar su fase de reconciliación, y luego se puede realizar el commit y podemos ver la actualización en la interfaz de usuario. E incluso con React 18, este proceso sigue siendo atómico por defecto.

Entonces, cuando hago clic en este botón de volver a renderizar y hago clic en el botón de cambiar estado global, simplemente estoy presionando ese botón hasta que se complete el renderizado. Luego podemos ver que la reconciliación acaba de ocurrir como un gran bloque, como una unidad atómica, y solo después de que se haya completado, React puede manejar los clics que se realizan en el botón. Pero ahora, con las características concurrentes, esto ha cambiado. Ahora tengo la posibilidad de programar una actualización de baja prioridad. Así que hagamos clic en ese botón y presionemos el botón de cambiar estado global. Como viste, vimos entre esos dos componentes, el primer bloque se renderizó aquí arriba. Y luego, después de esta fase de reconciliación del primer bloque, React tuvo tiempo o cedió al navegador. Entonces, el navegador pudo informarnos que hubo algunos eventos de clic. Así que React pudo actualizar este estado global. Y luego, después de que eso se maneje, React continuó el proceso de renderizado con los siguientes componentes, es decir, con el segundo bloque y luego con el tercer bloque.

Este proceso es un poco no determinista porque el navegador decide cuándo es el momento de hacer qué, por lo que es un poco difícil mostrarlo realmente. A veces, los cambios ocurrirán entre el segundo y el tercer componente, a veces en ambos, a veces la reconciliación aún ocurre de manera atómica. Pero ahora podemos ver que ya no tenemos esta garantía de que la fase de reconciliación sea atómica. Y ya podemos ver el primer problema. Si nos acercamos un poco aquí, podemos ver que el primer bloque se renderizó con un estado de 26, el segundo bloque se renderizó con un estado de 35 porque en ese tiempo hice clic en el botón 10 veces, por lo que los otros componentes muestran de repente un estado diferente que ya no está actualizado. Así que obtenemos este efecto de desgarro, donde vemos dos versiones diferentes de nuestra aplicación, dos versiones diferentes del estado dentro de la aplicación.

Entonces, necesitamos cambiar algo en nuestro código para evitar que esto suceda. Y lo que debemos hacer es dejar de leer valores que podrían cambiar fuera del mundo de React, es decir, dejar de leer algunos valores que pueden cambiar sin que React pueda saber que cambiaron. Esto significa que ya no podemos leer variables globales que son mutables. Por ejemplo, en mi ejemplo, este estado global es simplemente una variable de nivel de módulo definida con let, y esto se actualiza con el controlador de eventos. Y estamos leyendo esto en el componente, pero React simplemente no puede saber que alguien cambió esta variable simple. Para eso tendríamos que usar el hook useState o useReducer. Entonces, debemos dejar de hacer algo como eso, donde leemos algunos valores globales dentro de nuestro componente porque estos valores podrían cambiar durante la fase de reconciliación porque ya no es atómica. Lo mismo ocurre al leer refs. Los refs están específicamente hechos para objetos que pueden mutar alrededor de React sin que React tenga que reaccionar a eso.

4. Fase de Reconciliación y Fase de Commit

Short description:

Cuando leemos una referencia durante la fase de reconciliación, podemos encontrarnos con el problema de que la interfaz de usuario muestre diferentes versiones del estado. Esto también se aplica a la lectura del estado global desde una solución personalizada de gestión de estado. La garantía de React de fases de commit atómicas ya no se cumple con la introducción del modo estricto y las características de baja prioridad. La fase de reconciliación ahora puede ocurrir varias veces antes de una fase de commit, lo que puede llevar a inconsistencias potenciales en el estado. Esto se puede ver en nuestra demostración donde el DOM contiene brevemente elementos que luego se eliminan.

Entonces, cada vez que leemos una referencia durante la fase de reconciliación, por ejemplo, dentro del JSX, podemos encontrarnos con el mismo problema de que la interfaz de usuario muestra diferentes versiones del estado. Lo mismo ocurre cuando implementamos nuestra propia solución de gestión de estado personalizada, como Redux en 20 líneas, por ejemplo, y simplemente leemos el estado global desde nuestra solución personalizada de gestión de estado. Este es el mismo problema. Mientras esta solución no esté realmente integrada en React, podemos encontrarnos con problemas.

Vamos a hablar del segundo malentendido. Es que una fase de reconciliación o un renderizado siempre conduce a un commit. Lo que vimos antes es que tenemos esta fase de reconciliación y luego, cuando se completa, tenemos la fase de commit. Solo entonces se actualiza la interfaz de usuario. Incluso si dividimos la fase de reconciliación, todavía tenemos la garantía de React de que la fase de commit es atómica porque React no quiere mostrar diferentes versiones del estado. React quiere mostrar una vista consistente del estado de la aplicación. Por lo tanto, el commit siempre será atómico, pero la reconciliación puede tener pausas en el medio.

Ahora tenemos el problema de que ya no tenemos la garantía de que una fase de reconciliación siempre conduzca a exactamente una fase de commit. Ya escuchaste eso antes en la charla de Nick, donde te dijo que con el modo estricto de React, React renderiza tus componentes dos veces. Por lo tanto, React ya ejecuta tu fase de reconciliación dos veces para una sola fase de commit. Ahora, en el modo estricto, incluso hay dos fases de commit. Pero esto ya rompe la combinación de que siempre tenemos una fase de reconciliación y una fase de commit. También podemos ver eso en nuestra demostración. Ocultemos primero los bloques que tenemos disponibles aquí y marquemos esta casilla de verificación para mostrar los commits. Y ahora vamos a mostrar los bloques. Esto llevará nuevamente 15 segundos, cinco segundos por bloque. Y luego, antes de que esto se complete, vamos a hacer clic en el botón para ocultar los bloques nuevamente. Estoy haciendo clic en Mostrar Bloque y ahora estoy haciendo clic rápidamente en el botón Ocultar Bloques para que suceda lo más rápido posible. Podemos ver la fase de reconciliación ya que acabo de programar una actualización normal. Esto sigue siendo atómico, por lo que todavía pasamos por los tres bloques. El primero, cinco segundos, el segundo, cinco segundos, el tercero, cinco segundos. Y luego ocurre el commit. Por un breve momento, eso no fue realmente visible en la pantalla, pero por un breve momento, el DOM contenía esos tres bloques solo para que React los actualizara una vez más porque hicimos clic en el botón Ocultar Bloques para eliminar completamente los elementos nuevamente. Así que aquí podemos ver que tenemos una fase de reconciliación y una fase de actualización. Todo parece estar bien. Pero ahora, cuando usamos las características de baja prioridad de las características concurrentes de React, hacemos clic en Mostrar Bloques de Baja Prioridad y luego volvemos a hacer clic rápidamente en Ocultar Bloques.

5. Proceso de Reconciliación y Mundo Exterior

Short description:

React detiene el proceso de reconciliación si determina que los elementos no necesitan ser renderizados. Confiar en que React haga el commit después de la fase de reconciliación puede llevar a errores. Los componentes deben ser funciones puras que no lean ni muten el mundo exterior durante la reconciliación.

Y podemos ver que el proceso se aborta. Solo se reconcilió el primer elemento y luego React se detuvo porque React tuvo tiempo de manejar el evento, el clic en el otro botón que cambió el estado global para ocultar los bloques nuevamente para que React supiera, está bien, ni siquiera necesitamos renderizar esos otros elementos. Abortó por completo este proceso para que los bloques nunca fueran visibles en la interfaz de usuario. Así que tuvimos una fase de reconciliación en el primer bloque sin ningún commit. Entonces, cada vez que confiamos en el hecho de que React hará el commit después de la fase de reconciliación, estamos propensos a errores en nuestras aplicaciones. Eso significa nuevamente que debemos cambiar nuestro comportamiento. Debemos dejar de suscribirnos o mutar el mundo exterior dentro de la función de renderizado, dentro de la fase de reconciliación. Entonces, nuevamente, nuestros componentes deben ser funciones puras que no lean desde el mundo exterior si el mundo exterior puede cambiar y no se supone que mutemos el mundo exterior dentro de la fase de reconciliación.

6. Manejo de la Comunicación con el Mundo Exterior

Short description:

Existen tres opciones para manejar la comunicación con el mundo exterior en aplicaciones concurrentes de React. La primera opción es mover la comunicación dentro de un gancho UseEffect, asegurando que se devuelva una función de limpieza. La segunda opción es confiar en bibliotecas populares que ya son seguras para el modo concurrente. La tercera opción es utilizar el gancho useSyncExternalStore proporcionado por React, que permite sincronizar la aplicación con datos externos. Al elegir una de estas opciones, podemos asegurarnos de que la interfaz de usuario se mantenga consistente y evitar problemas de desgarro.

Para esto también tengo un par de ejemplos. Por ejemplo, hay algunas bibliotecas por ahí que registran oyentes de eventos o suscriptores a alguna solución de gestión de estado y lo hacen durante el proceso de renderizado. Así que aquí tenemos este componente ficticio que crea un oyente durante la fase de renderizado y lo agrega directamente al objeto window. Ahora imagina que este componente nunca se desmonta, entonces este oyente quedará atrapado en el objeto window y nadie lo eliminará nunca, por lo que tenemos una fuga de memoria en nuestra aplicación. Afortunadamente, este problema no ocurre realmente con demasiada frecuencia en las aplicaciones.

Esto ocurre más en el código de bibliotecas y por lo tanto, cuando te adhieres a bibliotecas populares, no te encontrarás realmente con ese problema, pero aún es importante tenerlo en cuenta, que no mutemos el mundo exterior, no construyamos una conexión, no creemos sockets web y cosas así porque esto podría romperse cuando usamos características concurrentes. Sin embargo, aún debe ser posible de alguna manera hacer estas cosas, leer valores globales, mutar el mundo exterior, porque al final, nuestra aplicación está hecha para comunicarse con un servidor, comunicarse con el usuario, mostrar algún estado cambiante, por lo que debe haber algunas soluciones.

La primera opción es simplemente mover toda esta comunicación dentro de UseEffect porque UseEffect está hecho para que tengamos la construcción, para que podamos hacer una conexión con un oyente de eventos y cosas así, y tenemos la limpieza, por lo que simplemente devolvemos otra función de limpieza desde UseEffect y podemos limpiar si creamos algunas conexiones, agregamos un oyente de eventos y luego lo eliminamos nuevamente cuando el componente se desmonta. Y dado que siempre tenemos esta garantía de que siempre habrá una limpieza después de la llamada a UseEffect, es seguro hacer algo así dentro de UseEffect. Así que siempre tenemos este patrón en el que tienes una variable de estado dentro de tu componente, lees desde el servidor dentro de UseEffect, actualizas la variable de estado, y luego estás listo. El problema con eso es que durante la primera fase de reconciliación, el efecto aún no se ha llamado, por lo que cuando necesites mostrar algo desde la llamada a UseEffect, debes hacer la primera fase de reconciliación sin este valor porque solo estará presente en la segunda fase cuando el estado se haya actualizado.

La segunda opción es elegir una biblioteca que se ajuste a tu caso de uso. Si eliges React Query para comunicarte con el servidor, si eliges algo como Redux Toolkit para manejar tus soluciones de gestión de estado, puedes confiar en las bibliotecas populares que ya son seguras para el modo concurrente porque el equipo de React ha estado trabajando muy de cerca con los mantenedores en este proceso de RFC para que estas bibliotecas ya sean seguras para el modo concurrente. Y la tercera opción es si realmente quieres manejar tu propia solución es usar useSyncExternalStore. Este es un gancho que React nos proporciona que podemos usar para sincronizar nuestra aplicación con algunos datos externos. Para eso, primero debes definir una función de suscripción, pero nuevamente tienes esta noción de construcción, un constructor, por así decirlo, y una limpieza donde debes garantizar que siempre se ejecutarán en pares. Entonces aquí, por ejemplo, agregamos un EventListener al evento global de cambio de tamaño y nos aseguramos de eliminarlo nuevamente una vez que este proceso de sincronización sea limpiado por React. Después de hacer eso, podemos construir un gancho personalizado, use windowWidth, por ejemplo, y usar el gancho useSyncExternalStore donde pasamos nuestra función de suscripción como primer argumento, y el segundo argumento es el valor que lee desde el mundo exterior. Y ahora React puede estar absolutamente seguro de controlar cuándo se llama esta función de lectura para que React pueda estar seguro de que este valor nunca cambia durante un proceso de reconciliación para que la interfaz de usuario siempre se mantenga consistente. De esta manera, podemos usar nuestro gancho personalizado, use windowWidth, donde queramos en nuestra aplicación, y podemos usar el valor durante la representación inicial de nuestro componente y estar seguros de que durante las actualizaciones, también se mantendrá actualizado y no introducirá problemas de desgarro. Eso significa que cuando usamos una de esas tres opciones, podemos relajarnos y dejar que React haga su trabajo porque el equipo de React diseñó React de tal manera que vivimos por encima de este nivel de abstracción. Entonces, en un mundo ideal, nunca nos preguntaríamos cuántas veces se llaman nuestras fases de reconciliación porque React podría tomar algunas decisiones en el futuro para llamarlas más a menudo, llamarlas menos a menudo, omitir algunas o volver a llamarlas. Si React puede confiar en que estas funciones son puras, entonces React puede decidir estas cosas por nosotros y puede hacer optimizaciones sin que nuestro código se rompa. Entonces, con estas suposiciones, ahora es posible volver a relajarse y mantenerse seguro en el mundo concurrente de React. Gracias por escuchar. Muchas gracias. Gracias. Gracias. Muchas gracias. Si quieres unirte aquí, tenemos algunas preguntas.

7. Modelos Mentales Comunes y Manejo del Estado en React

Short description:

Al trabajar con React, es importante entender que mutar valores fuera de React no es compatible. Los desarrolladores deben cambiar su modelo mental y utilizar ganchos como useState o useReducer para gestionar los cambios de estado. React requiere un control total sobre los cambios de estado para garantizar la consistencia.

Solo un recordatorio para la audiencia, pueden abrir Slido en cualquier momento y hacer preguntas a nuestros oradores hoy. Solo tenemos un par de preguntas hasta ahora, así que por favor, hagan preguntas. Probablemente tendremos tiempo para responderlas. Así que gracias una vez más por su charla. Continuaré con la primera pregunta que tenemos, que es, ¿cuáles son algunos de los modelos mentales comunes que ves en los desarrolladores que llevan a mutar valores fuera de React? Creo que es la forma normal de pensar que, por ejemplo, cuando tienes una variable que puedes usar para mostrar información en la interfaz de usuario. Lo mismo ocurre con las actualizaciones. Tenemos una característica en JavaScript llamada let, y puedes usarla para definir variables que puedes cambiar en el futuro, pero React no lo permite, o React no lo desea y probablemente no lo admita. Así que definitivamente hay algunas curvas de aprendizaje. Es especialmente importante cuando estás introduciendo a desarrolladores de React con otros antecedentes al mundo de React, porque definitivamente tienes que cambiar tu modelo mental para entrar en este mundo donde todo lo que cambia debe ir en un estado de uso o en un reductor de uso, porque solo entonces React tiene el control total sobre eso.

8. Linting Potential Issues in Component Usages

Short description:

¿Existe alguna forma de analizar problemas potenciales en el uso de componentes? Definitivamente. Ya existen muchas reglas de análisis estático en su lugar, como las matrices de dependencia para los efectos. También existen reglas relacionadas con las mutaciones, como la mutación de matrices u objetos. Las reglas de los hooks son importantes, al igual que las reglas relacionadas con las mutaciones y las variables mutables.

Excelente, gracias. La siguiente pregunta que tenemos, wow, tantos votos a favor, tan rápido. ¿Elon Musk, supongo? No te preocupes, esta es una audiencia encantadora. Solo te harán las preguntas más encantadoras. No te preocupes. ¿Existe alguna forma de analizar problemas potenciales en el uso de componentes? Sí, definitivamente. Y ya existen muchas reglas de análisis estático en su lugar. Por ejemplo, una de las cosas importantes son las matrices de dependencia. Así que cada vez que usamos los efectos, necesitamos agregar esas dependencias para que el efecto siempre se ejecute en los momentos en los que necesitamos que se ejecute. Supongo que también es bastante posible que existan reglas relacionadas con las mutaciones, porque cada vez que mutamos una matriz, mutamos un objeto, ya podemos saber, está bien, esto rompe estas suposiciones sobre el mundo inmutable de React. Así que definitivamente conozco las reglas de los hooks, que son bastante importantes. Y supongo que también debería haber algunas reglas relacionadas con las mutaciones, variables mutables, y cosas así.

9. Recommended Libraries for Synchronization

Short description:

¿Qué bibliotecas recomendarías para gestionar la sincronización en React? Las opciones populares para la obtención de datos incluyen React Query, que está integrado en muchas otras bibliotecas. Para la gestión del estado, contendientes como Zustand, Yotai y Valtio están diseñados específicamente para manejar los problemas que pueden surgir de las características concurrentes.

Excelente. Muchas gracias. Bien, ¿qué bibliotecas recomendarías? Mencionaste tres soluciones, siendo la opción intermedia el uso de bibliotecas. Sé que dijiste que depende mucho del caso de uso. ¿Existen algunas opciones principales a las que podrías recurrir para gestionar esta sincronización? Creo que las soluciones populares son simplemente para la obtención de data. Algo como React Query. Vimos anteriormente en la charla de TRPC que esto está integrado en muchas otras bibliotecas porque es muy confiable y manejan esos problemas bastante bien. Y para la gestión del estado, están los contendientes habituales como Zustand, Yotai, Valtio, y cosas así, que están diseñados específicamente para eso porque los mantenedores de esas bibliotecas también están bastante conscientes de los problemas que pueden surgir de las características concurrentes. Así que cuando elijas algo que sea popular y utilizado y mantenido activamente, puedes estar seguro de que el equipo ha comunicado con el equipo de React y puedes confiar en eso, creo.

10. Benefits of Concurrent Mode in Existing Frameworks

Short description:

¿Existen beneficios visibles al utilizar el modo concurrente en frameworks existentes como Gatsby o Next? Es realmente difícil mostrar los beneficios, como se ha demostrado en las discusiones en Twitter. El equipo de Rack cree que habrá beneficios en la programación del proceso de renderizado, pero es difícil proporcionar ejemplos. Las características de división de tiempo son importantes para el renderizado del lado del cliente, especialmente para aplicaciones con gráficos interactivos. Es posible que las páginas estáticas pre-renderizadas con Gatsby no muestren diferencias notables.

Genial. ¿Existen beneficios visibles al utilizar el modo concurrente en frameworks existentes como Gatsby o Next? Me gustaría profundizar en el primer punto de la pregunta. Creo que es realmente, realmente difícil mostrar los beneficios de eso. Ha habido muchas, muchas discusiones en Twitter donde se ha planteado esto, donde algunas personas hicieron algunas demostraciones con algunos cubos girando en un div y donde el framework podría mantenerse con características concurrentes. Y luego otros mantenedores de bibliotecas entran y dicen, nuestra biblioteca es tan rápida que no necesitamos esta concurrencia. Así que es realmente, realmente difícil decir si realmente habrá beneficios tangibles y medibles. El equipo de Rack tiene esta visión de que, dado que es teóricamente posible programar el renderizado del proceso de reconciliación, habrá beneficios allí, pero es realmente difícil mostrar ejemplos allí. Pero en teoría, debería ser bastante claro que siempre que el framework pueda decidir en qué quiere trabajar a continuación, porque algunas cosas son más importantes para el usuario que otras, debería haber algunos beneficios allí, pero nuevamente es realmente difícil mostrarlos. En cuanto a la integración en Next.js y Gatsby, todas esas características son especialmente importantes para, por lo que estas características de división de tiempo son especialmente importantes para el renderizado del lado del cliente. Por lo tanto, cuando tienes aplicaciones que hacen mucho en el lado del cliente, como algunos gráficos interactivos donde puedes filtrar los datos, por ejemplo, se vuelve realmente importante que la programación pueda mostrar realmente los beneficios. Cuando tienes una página estática que está pre-renderizada con Gatsby, por ejemplo, y solo muestra un artículo de blog, probablemente no notarás ninguna diferencia de todos modos.

11. Building Demos and Documentation Challenges

Short description:

Encontrar difícil construir demos para conceptos abstractos, el equipo de React luchó con la demostración del triángulo de Sierpinski. Se dieron cuenta de que era un ejemplo artificial y se alejaron de él. La documentación y la construcción de aplicaciones de muestra siempre son un desafío.

Sí, genial, gracias. Y sí, encontrar, ya sabes, una de las cosas más difíciles al construir demos para conceptos un poco más conceptuales y abstractos es que pueden ser un poco engreídos, y por lo tanto es difícil... Creo que el equipo de React también luchó con eso porque al principio, tenían esta demostración del triángulo de Sierpinski donde el triángulo se hacía más grande y más pequeño, y rápidamente se dieron cuenta de que esto solo tiene sentido realmente cuando se agregan algunos retrasos artificiales, como en mi demostración, porque entonces se pueden ver los efectos de estas características y se pueden demostrar, pero desde entonces se alejaron de eso porque se dieron cuenta de que estos son ejemplos realmente artificiales, y es realmente difícil imaginar cómo nos afecta en nuestras aplicaciones. Sí, siempre es un desafío con la documentación y la construcción de aplicaciones de muestra.

QnA

Enforcing Immutability and Real-World Use Cases

Short description:

¿Sería justo prohibir la palabra clave 'let' para imponer la inmutabilidad? Trabajar con el modo concurrente añade complejidad adicional, pero es opcional. React puede renderizar dos universos a la vez. Los casos de uso del mundo real para el modo concurrente son raros, pero incluyen la renderización de muchos componentes donde cada uno tarda más de lo habitual, como en gráficos o renderización 3D.

Correcto, tenemos un par de preguntas más. Aún podríamos tener tiempo para un par más, así que si tienen preguntas, no sean tímidos. Entonces, ¿impondrías, o tal vez, considerarías prohibir la palabra clave 'let' para imponer la inmutabilidad? Personalmente, no lo haría. Puedo entender si algunos lo hacen. Hay algunas personas en la community que siempre usan 'let' porque son solo tres letras en lugar de cinco, por lo que es más corto, y creo que es solo una cuestión de preferencia. Cuanto más tiempo trabajas con React, más resaltan esas patterns de mutaciones y actualizaciones como un dedo dolorido. En una revisión de código, se vuelve bastante claro, bastante evidente cuando alguien usa eso, y luego puedes ver si alguien usa 'let', ok, ¿qué está pasando aquí? ¿Está bien o no? Porque hay situaciones en las que esto está totalmente bien perder una variable 'let'. Por ejemplo, si tienes una función en un lado de esa función, en un controlador de eventos, por ejemplo, quieres actualizar una variable, está totalmente bien hacerlo siempre y cuando no mutemos nada que ya esté compartido con React para que React siempre pueda hacer un seguimiento de los data. Tan pronto como compartas algo, entonces debes detener la mutación y con esta precondición, es bastante difícil prohibir completamente algo porque todavía hay casos de uso disponibles para hacer eso.

Sí, absolutamente. Entonces, esta pregunta es, ¿sería justo decir que trabajar con el modo concurrente ahora añade complejidad adicional al trabajar con bibliotecas externas? Creo que esta es una de las principales quejas que se han planteado es que parece que de repente, React se volvió mucho más complejo con eso. En los primeros días, cuando tenías esas garantías que realmente no eran garantías de que todo sucede solo una vez y todo sucede de principio a fin, era más fácil razonar sobre los aspectos internos de React e incluir eso en las características que estabas desarrollando. Y ahora hay esta nueva capa de complejidad. Luego, Abolrov mencionó en Twitter que le gusta pensar que React ahora es capaz de renderizar dos universos a la vez, dos versiones del estado. Y creo que no se me habría ocurrido la idea de usar un marco de interfaz de usuario para renderizar dos universos, lo que creo que muestra bastante bien que sí, se vuelve más complejo, pero solo si realmente queremos aprovechar esas características concurrentes, porque también podemos decidir como equipo simplemente no usarlas, y luego estamos básicamente listos para continuar.

Genial. Esta probablemente sea la última pregunta a la que tendremos tiempo de responder. Y muchas gracias a todos los que enviaron preguntas. Terminamos con algo de excedente, y eso está perfectamente bien. Después de esta sesión de preguntas y respuestas, Andreas estará en la sección de preguntas y respuestas de los oradores en el área de networking. Así que por favor, si hicieron una pregunta para la que no tenemos tiempo, o si piensan en más preguntas en el ínterin, por favor, siéntanse libres de ir allí durante los próximos minutos y preguntarnos directamente. Entonces, esta última pregunta, que creo que es una continuación justa de algunas de nuestras preguntas anteriores, ¿puedes pensar en algún buen caso de uso del mundo real donde el modo concurrente realmente brille? Sí, creo que uno de los, así que tienes que tener un caso de uso donde tengas muchos componentes diferentes y donde cada componente tarde un poco más de lo habitual. Por ejemplo, tienes, para renderizar un frame, tienes 60 milisegundos. Entonces, por ejemplo, podrías decir que tienes como 1,000 componentes y cada uno tarda dos milisegundos. Este es un caso de uso perfecto porque React puede entonces recorrer como ocho componentes por ciclo de renderizado, luego ir al navegador y hacer algunas actualizaciones y luego continuar con este proceso de renderizado. Pero estos casos de uso son realmente raros porque cuando tienes una lista con 1,000 elementos, primero comienzas a virtualizar esa lista para que solo se rendericen los primeros 10 elementos que son visibles. Es por eso que creo que muchos de los demos usan algo como gráficos porque en los gráficos, sucede con bastante frecuencia que tienes como 1,000 puntos de data dentro de un gráfico. Pero luego el problema es, calcular uno de esos puntos de data a menudo es bastante barato. Por lo tanto, no obtenemos realmente los beneficios de eso. Paul Henschel de React 3.0 Fiber siempre muestra algunos demos interesantes porque allí está haciendo muchas cosas con renderizado 3D en el navegador.

Benefits of Concurrent Mode for Heavy Components

Short description:

Cuando colocas elementos en 3D en un componente, este puede crecer rápidamente en tamaño. Este es un buen caso de uso para las características concurrentes en React, especialmente al tratar con componentes pesados de tamaño mediano.

Y aquí tienes esto, cuando colocas un componente, cuando colocas elementos en 3D en un componente, este componente puede crecer rápidamente en tamaño en un tamaño relevante para el rendimiento. Así que creo que este es un caso de uso bastante bueno. Y por eso él es un gran defensor de esas características porque allí, realmente puedes aprovecharlas porque tienes una cantidad mediana de componentes pesados. Y creo que esta es la situación donde esto brilla más.

Excelente. Muchas gracias. Gracias de mi parte y estoy seguro de parte de la audiencia que te aplaudirá masivamente. Gracias por una charla tan esclarecedora. Muchas gracias por tenerme. Ha sido un placer. Gracias.

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

Una Guía del Comportamiento de Renderizado de React
React Advanced 2022React Advanced 2022
25 min
Una Guía del Comportamiento de Renderizado de React
Top Content
This transcription provides a brief guide to React rendering behavior. It explains the process of rendering, comparing new and old elements, and the importance of pure rendering without side effects. It also covers topics such as batching and double rendering, optimizing rendering and using context and Redux in React. Overall, it offers valuable insights for developers looking to understand and optimize React rendering.
Construyendo Mejores Sitios Web con Remix
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Construyendo Mejores Sitios Web con Remix
Top Content
Remix is a web framework built on React Router that focuses on web fundamentals, accessibility, performance, and flexibility. It delivers real HTML and SEO benefits, and allows for automatic updating of meta tags and styles. It provides features like login functionality, session management, and error handling. Remix is a server-rendered framework that can enhance sites with JavaScript but doesn't require it for basic functionality. It aims to create quality HTML-driven documents and is flexible for use with different web technologies and stacks.
Compilador React Forget - Entendiendo React Idiomático
React Advanced 2023React Advanced 2023
33 min
Compilador React Forget - Entendiendo React Idiomático
Top Content
Joe Savona
Mofei Zhang
2 authors
The Talk discusses React Forget, a compiler built at Meta that aims to optimize client-side React development. It explores the use of memoization to improve performance and the vision of Forget to automatically determine dependencies at build time. Forget is named with an F-word pun and has the potential to optimize server builds and enable dead code elimination. The team plans to make Forget open-source and is focused on ensuring its quality before release.
Uso efectivo de useEffect
React Advanced 2022React Advanced 2022
30 min
Uso efectivo de useEffect
Top Content
Today's Talk explores the use of the useEffect hook in React development, covering topics such as fetching data, handling race conditions and cleanup, and optimizing performance. It also discusses the correct use of useEffect in React 18, the distinction between Activity Effects and Action Effects, and the potential misuse of useEffect. The Talk highlights the benefits of using useQuery or SWR for data fetching, the problems with using useEffect for initializing global singletons, and the use of state machines for handling effects. The speaker also recommends exploring the beta React docs and using tools like the stately.ai editor for visualizing state machines.
Enrutamiento en React 18 y más allá
React Summit 2022React Summit 2022
20 min
Enrutamiento en React 18 y más allá
Top Content
Routing in React 18 brings a native app-like user experience and allows applications to transition between different environments. React Router and Next.js have different approaches to routing, with React Router using component-based routing and Next.js using file system-based routing. React server components provide the primitives to address the disadvantages of multipage applications while maintaining the same user experience. Improving navigation and routing in React involves including loading UI, pre-rendering parts of the screen, and using server components for more performant experiences. Next.js and Remix are moving towards a converging solution by combining component-based routing with file system routing.
Concurrencia en React, Explicada
React Summit 2023React Summit 2023
23 min
Concurrencia en React, Explicada
Top Content
React 18's concurrent rendering, specifically the useTransition hook, optimizes app performance by allowing non-urgent updates to be processed without freezing the UI. However, there are drawbacks such as longer processing time for non-urgent updates and increased CPU usage. The useTransition hook works similarly to throttling or bouncing, making it useful for addressing performance issues caused by multiple small components. Libraries like React Query may require the use of alternative APIs to handle urgent and non-urgent updates effectively.

Workshops on related topic

Masterclass de Depuración de Rendimiento de React
React Summit 2023React Summit 2023
170 min
Masterclass de Depuración de Rendimiento de React
Top Content
Featured Workshop
Ivan Akulov
Ivan Akulov
Los primeros intentos de Ivan en la depuración de rendimiento fueron caóticos. Vería una interacción lenta, intentaría una optimización aleatoria, vería que no ayudaba, y seguiría intentando otras optimizaciones hasta que encontraba la correcta (o se rendía).
En aquel entonces, Ivan no sabía cómo usar bien las herramientas de rendimiento. Haría una grabación en Chrome DevTools o React Profiler, la examinaría, intentaría hacer clic en cosas aleatorias, y luego la cerraría frustrado unos minutos después. Ahora, Ivan sabe exactamente dónde y qué buscar. Y en esta masterclass, Ivan te enseñará eso también.
Así es como va a funcionar. Tomaremos una aplicación lenta → la depuraremos (usando herramientas como Chrome DevTools, React Profiler, y why-did-you-render) → identificaremos el cuello de botella → y luego repetiremos, varias veces más. No hablaremos de las soluciones (en el 90% de los casos, es simplemente el viejo y regular useMemo() o memo()). Pero hablaremos de todo lo que viene antes - y aprenderemos a analizar cualquier problema de rendimiento de React, paso a paso.
(Nota: Esta masterclass es más adecuada para ingenieros que ya están familiarizados con cómo funcionan useMemo() y memo() - pero quieren mejorar en el uso de las herramientas de rendimiento alrededor de React. Además, estaremos cubriendo el rendimiento de la interacción, no la velocidad de carga, por lo que no escucharás una palabra sobre Lighthouse 🤐)
Next.js para Desarrolladores de React.js
React Day Berlin 2023React Day Berlin 2023
157 min
Next.js para Desarrolladores de React.js
Top Content
Featured WorkshopFree
Adrian Hajdin
Adrian Hajdin
En esta avanzada masterclass de Next.js, profundizaremos en conceptos clave y técnicas que permiten a los desarrolladores de React.js aprovechar al máximo Next.js. Exploraremos temas avanzados y prácticas prácticas, equipándote con las habilidades necesarias para construir aplicaciones web de alto rendimiento y tomar decisiones arquitectónicas informadas.
Al final de esta masterclass, serás capaz de:1. Comprender los beneficios de los Componentes del Servidor React y su papel en la construcción de aplicaciones React interactivas, renderizadas por el servidor.2. Diferenciar entre el tiempo de ejecución de Edge y Node.js en Next.js y saber cuándo usar cada uno en función de los requisitos de tu proyecto.3. Explorar técnicas avanzadas de Renderizado del Lado del Servidor (SSR), incluyendo streaming, fetching paralelo vs. secuencial, y sincronización de datos.4. Implementar estrategias de caché para mejorar el rendimiento y reducir la carga del servidor en las aplicaciones Next.js.5. Utilizar Acciones React para manejar la mutación compleja del servidor.6. Optimizar tus aplicaciones Next.js para SEO, compartir en redes sociales, y rendimiento general para mejorar la descubrabilidad y la participación del usuario.
Aventuras de Renderizado Concurrente en React 18
React Advanced 2021React Advanced 2021
132 min
Aventuras de Renderizado Concurrente en React 18
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
Con el lanzamiento de React 18 finalmente obtenemos el tan esperado renderizado concurrente. Pero, ¿cómo va a afectar eso a tu aplicación? ¿Cuáles son los beneficios del renderizado concurrente en React? ¿Qué necesitas hacer para cambiar al renderizado concurrente cuando actualices a React 18? ¿Y qué pasa si no quieres o no puedes usar el renderizado concurrente todavía?

¡Hay algunos cambios de comportamiento de los que debes estar al tanto! En esta masterclass cubriremos todos esos temas y más.

Acompáñame con tu portátil en esta masterclass interactiva. Verás lo fácil que es cambiar al renderizado concurrente en tu aplicación React. Aprenderás todo sobre el renderizado concurrente, SuspenseList, la API startTransition y más.
Consejos sobre React Hooks que solo los profesionales conocen
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
Consejos sobre React Hooks que solo los profesionales conocen
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
La adición de la API de hooks a React fue un cambio bastante importante. Antes de los hooks, la mayoría de los componentos tenían que ser basados en clases. Ahora, con los hooks, estos son a menudo componentes funcionales mucho más simples. Los hooks pueden ser realmente simples de usar. Casi engañosamente simples. Porque todavía hay muchas formas en las que puedes equivocarte con los hooks. Y a menudo resulta que hay muchas formas en las que puedes mejorar tus componentes con una mejor comprensión de cómo se puede usar cada hook de React.Aprenderás todo sobre los pros y los contras de los diversos hooks. Aprenderás cuándo usar useState() versus useReducer(). Veremos cómo usar useContext() de manera eficiente. Verás cuándo usar useLayoutEffect() y cuándo useEffect() es mejor.
Presentando FlashList: Construyamos juntos una lista performante en React Native
React Advanced 2022React Advanced 2022
81 min
Presentando FlashList: Construyamos juntos una lista performante en React Native
Top Content
Featured Workshop
David Cortés Fulla
Marek Fořt
Talha Naqvi
3 authors
En esta masterclass aprenderás por qué creamos FlashList en Shopify y cómo puedes usarlo en tu código hoy. Te mostraremos cómo tomar una lista que no es performante en FlatList y hacerla performante usando FlashList con mínimo esfuerzo. Usaremos herramientas como Flipper, nuestro propio código de benchmarking, y te enseñaremos cómo la API de FlashList puede cubrir casos de uso más complejos y aún así mantener un rendimiento de primera categoría.Sabrás:- Breve presentación sobre qué es FlashList, por qué lo construimos, etc.- Migrando de FlatList a FlashList- Enseñando cómo escribir una lista performante- Utilizando las herramientas proporcionadas por la biblioteca FlashList (principalmente el hook useBenchmark)- Usando los plugins de Flipper (gráfico de llamas, nuestro perfilador de listas, perfilador de UI & JS FPS, etc.)- Optimizando el rendimiento de FlashList utilizando props más avanzados como `getType`- 5-6 tareas de muestra donde descubriremos y solucionaremos problemas juntos- Preguntas y respuestas con el equipo de Shopify
React, TypeScript y TDD
React Advanced 2021React Advanced 2021
174 min
React, TypeScript y TDD
Top Content
Featured Workshop
Paul Everitt
Paul Everitt
ReactJS es extremadamente popular y, por lo tanto, ampliamente soportado. TypeScript está ganando popularidad y, por lo tanto, cada vez más soportado.

¿Los dos juntos? No tanto. Dado que ambos cambian rápidamente, es difícil encontrar materiales de aprendizaje precisos.

¿React+TypeScript, con los IDEs de JetBrains? Esa combinación de tres partes es el tema de esta serie. Mostraremos un poco sobre mucho. Es decir, los pasos clave para ser productivo, en el IDE, para proyectos de React utilizando TypeScript. En el camino, mostraremos el desarrollo guiado por pruebas y enfatizaremos consejos y trucos en el IDE.