Aventuras de Renderizado Concurrente en React 18

Rate this content
Bookmark

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.

Maurice de Beijer
Maurice de Beijer
132 min
27 Oct, 2021

Comments

Sign in or register to post your comment.
  • Narges Haeri
    Narges Haeri
    Aspiring Professional
    Thank you so much for such great content. Your workshop was incredibly helpful!

Video Summary and Transcription

La masterclass aborda las nuevas características de React 17 y React 18, incluyendo suspense, manejo de errores y modo concurrente. Enfatiza la importancia del aprendizaje práctico y la escritura de código en lugar de simplemente copiar. La masterclass explora el uso de suspense y límites de error para manejar errores y mejorar la experiencia del usuario. También introduce nuevas características en React 18, como start transition y useTransition, para mejorar la capacidad de respuesta. Se discute la interacción entre suspense y start transition, destacando su colaboración en el manejo de la interfaz de usuario de fallback y la comunicación.

Available in English

1. Introducción a la Renderización Concurrente

Short description:

Bienvenidos a la masterclass sobre aventuras de renderización concurrente en React18. Soy Maurice de Beer, un instructor de desarrollo independiente y Microsoft MVP. Sígueme en Twitter y visita mi sitio web para más información. Suscríbete a mi boletín semanal de React para actualizaciones. Recibirás una copia de las diapositivas también.

Bueno, es hora de empezar. Bienvenidos a todos a esta workshop sobre aventuras de concurrent rendering en React18. Ayuda si la ventana correcta está enfocada. ¿Quién soy? Mi nombre es Maurice de Beer, también conocido como el solucionador de problemas. Soy un Microsoft MVP entre otras cosas, lo que no significa que trabaje para Microsoft. Pero de alguna manera hago su marketing de forma gratuita ocasionalmente, lo que supongo que me da el peor final del trato, pero me dan un montón de software gratuito y otras cosas. También soy un instructor de desarrollo independiente. Creo en combinar los dos, porque si desarrollo, entonces cuando enseño, puedo decirle a la gente lo que realmente funciona. Cuando enseño, tengo que seguir pensando en cosas nuevas, otras formas, mejores formas de hacer cosas, lo que me mantiene agudo como desarrollador, así que funciona bien juntos. También estoy en Twitter, si quieres seguirme, mi sitio web está aquí y puedes escanear el QR code, llegarás a mi sitio web también y a mi dirección de correo electrónico. También publico un boletín semanal, el boletín de React. Estamos en el número 310 o algo así, así que llevo un tiempo haciéndolo. Puedes escanear el QR code aquí y te llevará a un formulario de registro donde puedes poner tu nombre y dirección de correo electrónico. Recibirás un boletín a la semana, todos los miércoles. Así que el de hoy salió hace una hora, pero la próxima semana saldrá otro. No voy a usar tu correo electrónico para nada más, así que no te preocupes por recibir spam y cosas así, o por vender tu dirección de correo electrónico a otras empresas. Hay enormes listas de direcciones de correo electrónico filtradas por las grandes empresas, así que mi pequeña lista no va a ser muy influyente allí. Y si no te gusta el boletín, puedes darte de baja en cualquier momento. Recibirás una copia de estas diapositivas, así que si no tuviste la oportunidad de escanear el QR code o eso, lo recibirás de todos modos.

2. Explorando las características de React 17 y React 18

Short description:

Exploraremos las nuevas características de React 17 y React 18, incluyendo suspense, manejo de errores, renderización de aplicaciones existentes, lista de suspense, transiciones y modo concurrente. Por favor, ten en cuenta que no cubriremos todas las características de React 18, como la renderización en el lado del servidor con suspense.

Entonces, ¿cuál es el objetivo de la masterclass? Vamos a echar un vistazo a lo nuevo en la renderización concurrente, suspense, en cierto grado a lo que no es nuevo. Vamos a empezar con algunas cosas en React 17 porque lo que podemos hacer con suspense ahora es bastante importante. Así que vamos a ver cómo usar suspense, cómo paralizar el suspense anidado, cómo manejar los errores que ocurren en un límite de suspense. Luego vamos a cambiar a React 18 que todavía está en vista previa en este momento, no lanzado todavía. Veremos cómo podemos renderizar la aplicación existente de React en React 18 usando CreateRoute. Veremos nuevas capacidades de suspense con cosas como la lista de suspense y las transiciones. Veremos qué hace el modo concurrente, cómo podría influir potencialmente en el rendimiento de tu aplicación bastante y cómo lo harías. Echaremos un vistazo a algunos otros bits. No vamos a mirar todo lo que React 18 tiene para ofrecer. Hay mucho más. Había un montón de cosas de renderización en el lado del servidor allí como actualmente con React 17 no puedes hacer renderización en el lado del servidor con suspense. Con React 18, si solías crear la API de ruta, puedes, pero eso no es algo que vamos a cubrir.

3. Consejos sobre Aprendizaje y Escritura

Short description:

Tu memoria funciona mejor si haces cosas. Intenta hacer los ejercicios en lugar de solo mirar y copiar código. Cometer errores de tipeo y reconocer errores te ayudará a aprender. Copiar y pegar no es suficiente en el desarrollo de aplicaciones reales. Escribir las cosas es beneficioso para el aprendizaje.

Un poco de advice. Tu memoria funciona mejor si haces cosas. Si solo ves la presentación y copias y pegas todo el code de los ejercicios, está bien si quieres hacer eso, pero no recordarás casi tanto como si realmente intentas hacerlo. Si lo haces, cometerás errores de tipeo. Yo cometo muchos errores de tipeo. Esos errores de tipeo resultarán en errores y reconocerás esos errores cuando vuelvan a ocurrir. Porque cuando realmente construyes aplicaciones, no puedes simplemente copiar y pegar. Sería muy agradable si pudieras copiar y pegar tu aplicación completa. Pero de nuevo, si puedes, cualquiera puede, y ¿por qué nos pagan buen dinero por construir aplicaciones si todo lo que necesitas hacer es ser capaz de copiar y pegar. Así que ayuda a tus células cerebrales y escribe las cosas.

4. Prerrequisitos y Configuración

Short description:

Para comenzar, asegúrate de tener Node y npm configurados. Verifica las versiones usando 'node -v' y 'npm -v'. Clona el repositorio inicial de GitHub e instala los paquetes npm. Abre Visual Studio Code y ejecuta 'npm start'. La aplicación muestra una lista de usuarios con detalles y una lista de números primos. La renderización puede ser lenta, especialmente con números más grandes. La masterclass incluye diapositivas interactivas con ejemplos de código y enlaces al repositorio de GitHub.

También hay algunos prerrequisitos. Ahora, esta no es una masterclass para principiantes de React, así que voy a suponer que todos tienen Node y npm configurados, pero por si acaso, vamos a verificar. Y luego vamos a comenzar con el repositorio inicial de GitHub que va a ser la base de todo lo que vamos a trabajar. Lo tengo preparado, y te mostraré en un segundo cómo configurarlo. Pero primero, los prerrequisitos.

Si abres una ventana de terminal, y haces node-version, o node-v, te dirá la versión de Node, y eso debería ser algo como Node 14, o posterior. No estoy 100% seguro de cuál es la última versión. De hecho, puedo verificarlo simplemente haciendo clic en eso. Y por supuesto, eso se abre en mi otra ventana. Así que la versión actual es en realidad 16.13. No necesitas estar en la última versión. Si estás en algún lugar en Node 14 o posterior, está bien. Y luego presumiblemente 12, o posterior está bien. Lo mismo con NPM, si haces NPM –version, o NPM –v, te dirá la versión de NPM. Estoy en 7.24. Creo que la última ya está en ocho y algo, pero cualquier cosa con la versión seis o posterior debería estar bien. Así que si abro una ventana de terminal aquí, y hago esto un poco más grande, hago node –v, y ¿mencioné algo sobre hacer errores de tipeo? Pero puedes ver que estoy en 14.18 y NPM –v me dice que estoy en 7.24, las mismas versiones que en la diapositiva. Luego necesitamos el repositorio, el repositorio inicial. Así que lo tengo en GitHub. Copiaré ese enlace en un momento a la ventana de chat. Pero eso te llevará aquí a GitHub. Puedes clonar este repositorio. Copia eso, ve a la terminal y haz un git clone con esa URL y eso debería clonar el repositorio. No es muy grande, así que no debería tardar mucho. Cd en él y podemos hacer un npm install, npm i o npm ci si quieres, lo que prefieras y comenzará a instalar todos los paquetes de npm.

Así que déjame copiar esta URL del repositorio de GitHub en la ventana de chat en Discord. Y por si acaso la gente no llegó a Discord en zoom también. Así que eso está instalado, déjame abrir Visual Studio Code antes de que realmente inicie la aplicación y te muestre lo que hace. Así que se creó con create react app. Así que el usual npm start para iniciarlo. Y eso es muy especial allí. Comienza y sigue abriéndose. En la otra ventana, eso está bien. Ahí está. Es una aplicación simple, tenemos una lista de usuarios aquí. Si hago clic en el usuario, vemos algunos detalles del usuario. Y vemos algunos detalles sobre su película favorita. Lo mismo aquí. Nota cuando cargo los detalles, aparecen dos spinners. Y la película favorita siempre termina primero. Así que eso se resuelve primero, y los detalles del usuario siempre se resuelven al final. Eso está hecho artificialmente, porque he añadido un poco de peso allí. Pero eso es algo a lo que volveremos varias veces durante la masterclass. También hay una lista de números primos, porque toda buena aplicación de negocios necesita una lista de números primos. Bueno, en realidad tal vez no, pero es útil aquí, no porque sean números primos, sino porque es costoso renderizar una lista de números primos. Y la renderización lenta y costosa es algo que surge bastante a menudo con aplicaciones más grandes. Así que esto es algo artificial, pero sí sirve a un propósito. Ahora si tomo el deslizador, puedes ver que puedo moverlo y recalcula esa lista de números. Algo responsivo aquí. Pero si voy a números más grandes, de repente ya no es tan responsivo. Así que estoy arrastrando mi ratón sobre el deslizador y puedes ver que se queda atrás. E incluso si solo hago clic como estoy haciendo ahora, puedes ver que tarda un poco de tiempo, y si voy a los números muy grandes, hasta un millón, si hago clic puedes ver que no es muy responsivo en absoluto, lo cual es algo que podemos arreglar con concurrent rendering. De vuelta a las diapositivas. Así que ese es el repositorio clonado. Esa es la instalación de NPM que acabo de hacer.

Ahora, hay muchos bits interactivos en este flujo de trabajo, y prácticamente cada vez que voy a escribir code, va a haber, o no prácticamente, cada vez que voy a escribir code, va a haber una diapositiva como esta, y estas diapositivas son en realidad enlaces. Si haces clic en ellos, llegas al repositorio de GitHub y llegas al commit actual, que contiene ese cambio. Así que aquí en la diapositiva podrías ver algo sobre suspense, y detalles de películas, y cosas así. Y puedes ver aquí con el verde, añadí el límite de suspense alrededor del code existente. Por supuesto puedes ir y copiar esto. Es code, después de todo. Pero como mencioné antes, es mejor usar esto como un ejemplo de qué hacer que copiarlo realmente. Pero, por supuesto, al final, eso depende de ti. También tengo un enlace al repositorio aquí, también un enlace a la baraja de diapositivas. Y déjame copiar y pegar esto en la ventana de Slack, o en la ventana de Discord, y en el chat de Zoom también. Porque eso hace mucho más fácil hacer clic en esas imágenes. Como puedo desplazarme hacia abajo aquí y... ¿dónde estaba ese primer aquí? Hago clic en él y... Esta página está tardando demasiado en cargar, eso es agradable.

5. Salas de Grupo y Ejecución de Tareas

Short description:

GitHub está dando problemas. Vamos a utilizar las salas de grupo de Zoom. Las abriré siempre que sea el momento de hacer algo. La mayoría de las tareas son relativamente cortas, así que las abriré en unos cinco minutos. Si ya has terminado con lo que sea que necesites hacer, siéntete libre de dejar la sala de grupo, vuelve a la sala principal.

GitHub está dando problemas. Ahí está. Actualicé y sí apareció. Otra cosa que verás es al Capitán Jean-Luc Picard con su famoso Make It So. Esa es básicamente tu señal para empezar a hacer algo. Vamos a utilizar las salas de grupo de Zoom. Las abriré siempre que sea el momento de hacer algo. Dependiendo de cuál sea la tarea actual, lo haré un poco más largo o más corto. La mayoría de las tareas son relativamente cortas, así que las abriré en unos cinco minutos. Si ya has terminado con lo que sea que necesites hacer, siéntete libre de dejar la sala de grupo, vuelve a la sala principal. Si veo que todos han dejado la sala de grupo, no hay necesidad de esperar. Podemos simplemente continuar con el siguiente paso. Si no, voy a esperar a que se agote el tiempo.

6. Entendiendo React 17 y Suspense

Short description:

Comenzamos con React 17 y usamos suspense para suspender la renderización de componentes. Suspense se activa al lanzar una promesa, típicamente una solicitud AJAX, dentro del renderizado. Cuando la promesa se resuelve, el componente se vuelve a renderizar. Los errores son manejados por los límites de error. La biblioteca SWR puede ser configurada para usar suspense. Agregar un límite de suspense y un mecanismo de fallback soluciona las aplicaciones rotas. TypeScript se utiliza en esta masterclass.

Entonces, continuemos. Como mencioné en la introducción, la primera parte, en realidad vamos a comenzar con React 17 y cómo podemos usar suspense dentro de React 17 y qué beneficio aporta, y luego construiremos sobre eso cuando lleguemos a React 18. Ahora, veamos qué está pasando.

Entonces, esta es la base que necesitamos cubrir para asegurarnos de que podemos trabajar con suspense de React 18 y suspense list y este tipo de cosas. Ahora, con React 17, obtuvimos el componente suspense y el componente suspense nos permitirá suspender algún trabajo que está en curso. ¿Qué significa realmente este trabajo en términos de React? Bueno, suspendes la renderización de un componente o un subárbol de componentes lanzando una promesa dentro del renderizado, lo cual es un poco extraño. Si piensas en la palabra clave throw en JavaScript o TypeScript, piensas en errores. Lanzas un error. Pero JavaScript te permite lanzar cualquier cosa. Puedes lanzar un número o una cadena. React en realidad usa eso diciendo, bueno, vamos a lanzar una promesa cuando algo suceda donde no podamos terminar de renderizar. Y ese algo podría ser cualquier cosa, pero típicamente eso significa que estás haciendo una solicitud AJAX para obtener algo del servidor. Pero de nuevo, podría ser algo completamente diferente, pero ese va a ser el caso más común.

Y ese algo del servidor típicamente es una de dos cosas. O bien estás haciendo una solicitud AJAX donde estás obteniendo data que quieres renderizar. O lo otro es que estás cargando componentes de forma perezosa y estás haciendo una solicitud AJAX para cargar de forma perezosa algunos códigos para que puedas renderizar ese componente. Pero aún no ha sido cargado, por lo que aún no está disponible. Y luego, cuando se lanza esa promesa, React básicamente dice, está bien, vamos a suspender este componente o ese subárbol de componentes, y vamos a esperar a que esa promesa esté terminada. Y una promesa puede terminar de una de dos maneras. Puede simplemente rechazar, en cuyo caso hay un error, o puede resolver, en cuyo caso hay éxito. Y si el subárbol de componentes está suspendido y la promesa que lo suspendió se resuelve, entonces React dice está bien, vamos a renderizar ese subárbol de nuevo y presumiblemente lo que lo hizo suspender ya está hecho, por lo que se renderizará y producirá lo que sea, bueno, marcado elementos DOM que queremos. Potencialmente podría suspenderse de nuevo para obtener más data. Y en caso de error, React va a decir está bien, en ese caso hay un error, vamos a llamar a un límite de error o vamos a buscar un límite de error y vamos a dejar que haga su cosa y si no hay un límite de error, en realidad vamos a matar la aplicación.

Ahora la aplicación que estoy usando obtiene data. Y si vamos a los componentes de origen, y por ejemplo, en usuarios, hay estos detalles de cuenta. Podemos ver aquí que utiliza el hook use SWR. Así que es un hook de obtención de data de Vercel llamado Stale While Revalidate. Así que obtiene data y vuelve a obtener data, etc. Y eso es una solicitud AJAX. Tenemos el code tradicional aquí, manejar errores, si hubo algún error, si no tenemos ninguna data todavía, mostraremos algún tipo de indicador de carga que estamos cargando y eso es lo que realmente muestra ese spinner. Cuando refresco, ya tenía alguna data en caché. El spinner que aparece aquí, eso es la carga. Y si la data está ahí, entonces ninguno de estos va a renderizar y en realidad va a ir justo aquí. Y por supuesto si hay un error, permíteme rápidamente introducir un error haciendo esa URL inválida. Así que ahora si hago clic en el usuario, vemos un spinner y luego vemos no encontrado porque esa URL era en realidad inválida. Pero hagámosla válida de nuevo. Resulta que SWR, la biblioteca de obtención de data no funciona con suspense de serie, pero es realmente fácil hacer que lo haga. En el index.js hay esta configuración de SWR, y tiene react-context debajo del capó. Y proporcionamos algún contexto sobre cómo debería funcionar SWR. Y tiene una opción allí, suspense, que por defecto es falso, pero podemos establecer eso en verdadero. Y ahora empezará a usar suspense automáticamente, a menos que sea anulado por algún otro, podríamos anular esto en un caso individual, pero no lo estamos haciendo. De repente, todas nuestras solicitudes Ajax han cambiado a suspense. Ahora esto es específico de la forma en que funciona SWR, pero si estás usando React query, por ejemplo, tiene prácticamente la misma configuración y muchas bibliotecas de React para obtener data harán lo mismo. Si estás usando React lazy para cargar componentes de forma perezosa, se enganchará automáticamente a suspense. No puedes ni siquiera apagarlo, siempre lo hará. Sin embargo, ahora mi aplicación está rota. Si me aseguro de que mis cachés están limpias presionando un 5, voy a usuarios, obtenemos un error. Oops, algo salió mal. La lista de usuarios, que era esa lista de usuarios que aparecía antes, está siendo obtenida ahora, pero empezó a usar suspense. Y eso significa que necesitamos tener este mecanismo de fallback de suspense. Así que en algún lugar necesito añadir un límite de suspense. Y normalmente los añado en varios lugares. Pero empezaré en la raíz misma. Y añadiremos más más tarde. Y queremos algún fallback así que tengo un componente de carga. Y eso no se resuelve del todo hasta que tengo el insuspense. Ahora eso debería resolver la importación. Así que tengo un objeto suspense. Y ahora si vuelvo a la raíz, y ahora hago las mismas aventuras de renderizado concurrente, vemos que en realidad obtiene su data y utiliza suspense allí. Y si hago clic en el usuario, carga la data. Ahora podrías haber notado que hay una diferencia de comportamiento porque originalmente cuando hacía clic en el usuario, veríamos dos spinners aquí, uno para los detalles del usuario y otro para los usuarios favoritos. Ahora, de repente, toda la UI es reemplazada por un solo spinner, así que no muy agradable, diría yo. En realidad lo arreglaremos en un minuto porque podemos hacer bastante con suspense. Pero si miramos esos detalles de la cuenta ahora, es como, bueno, ¿vamos a tener errores? No, porque con suspense, los errores son manejados de una manera diferente, así que podemos deshacernos de ese error. Si aún no tenemos data, ¿necesitamos mostrar un indicador de carga? No, porque con suspense, todo ese mecanismo de lanzar una promesa entra en juego. Así que nunca deberíamos llegar aquí sin ninguna data, así que deberíamos poder deshacernos de eso. Ahora estoy usando TypeScript, y espero que todos sean fans de TypeScript. Soy un fan de TypeScript y este trabajo de serie de React o trabajo de front-end lo hago con TypeScript o bastante trabajo de backend también. Así que en realidad se queja aquí diciendo, bueno, la cuenta es una cuenta o indefinida. Eso es porque la API aquí debajo del capó está usando suspense así que de alguna manera sabemos que esta cuenta realmente es una cuenta o se va a lanzar una promesa.

7. Uso de Suspense y Límites de Error

Short description:

En esta sección, aprendimos sobre el uso de suspense en React 17. Usamos TypeScript para manejar posibles valores indefinidos y eliminamos código innecesario. También exploramos la biblioteca SWR para la obtención de datos y añadimos límites de suspense a nuestra aplicación. El comportamiento de carga puede ser mejorado, lo cual abordaremos más adelante.

Nunca va a ser indefinido. Si algo salió mal, no llegaremos aquí, llegaremos a un límite de error, excepto que la tipificación realmente no puede saber que estamos usando suspense, por lo que la tipificación realmente asume, bueno, la cuenta podría ser indefinida. Así que un pequeño truco con TypeScript es que no puedes cambiar eso en línea para que no sea indefinido. Ahora, tengo exactamente lo mismo, pero ahora puedo poner un signo de exclamación detrás de esto diciendo, bueno, data es quizás una cuenta o indefinida pero sé que nunca es indefinida por lo que siempre es un objeto. Así que si reviso el tipo de cuenta siempre es una cuenta no indefinida, y mis errores de compilación desaparecen. Y he eliminado bastante code. Puedo hacer lo mismo con los detalles de la película, esa parte de error y no cargada desaparece. No necesito ese error más. Y esta película siempre es un objeto. Así que lo mismo con el signo de exclamación. En la lista de usuarios, tenemos un code similar, mucho code similar allí. En realidad no renombré los data. Solo estoy usando data aquí. Y ahora tenemos un error de compilación justo aquí diciendo objeto posiblemente indefinido. Así que de nuevo, un signo de exclamación o podría potencialmente poner un signo de interrogación o podría usar otra forma en TypeScript para hacerlo, el operador de coalescencia nulo. Cualquiera funcionará. Así que me deshice de muchas cosas extra allí que no necesitábamos y en realidad tengo algunas entradas aquí que puedo eliminar también. ¿Dónde estaba el otro? Ahí, ese es el que estaba buscando. Vale. Así que, asegúrate de que todo funciona. Puedo cargar los usuarios, los data aparecen. El comportamiento de carga no es perfecto como mencioné pero lo arreglaremos más tarde. Así que esos son los fundamentos de suspense. Recuerda ese componente de fallback o prop de fallback que tienes que especificar para suspense. Puede ser un componente, podría ser solo una cadena. Funciona realmente bien. Hay un ligero cambio de comportamiento con suspense en React 18 con esa prop de fallback pero hablaré más sobre eso cuando lleguemos a React 18. Así que aquí está SWR que estamos usando para obtener data. Una utilidad bastante agradable y conveniente para usar para eso. El cambio que hice allí, añadiendo suspenses a través de la configuración de SWR y añadiendo el límite de suspense justo en la raíz de nuestra aplicación. Algo así como un último recurso para atrapar todos los suspenses. La actualización a las listas de usuarios, detalles de la cuenta, y detalles de la película, donde no hay una flecha porque todo lo que hice fue eliminar code. Bueno, prácticamente eliminé code. Así que no había mucho que mostrar Lo cual funciona realmente bien. Y por supuesto, los resultados. Esto es cuando realmente está cargando, lo cual no es tan agradable, pero lo arreglaremos en un minuto.

8. Explorando el Manejo de Errores y los Límites de Suspense

Short description:

Vamos a abrir las salas de trabajo en grupo de nuevo por un tiempo más largo. Proporcionaré el enlace del repositorio a Ravi. Luego, exploraremos el manejo de errores, la orquestación de los límites de suspense y los resultados obtenidos.

Así que vamos a hacer esto. Voy a abrir las salas de trabajo en grupo de nuevo. Lo haré por un tiempo un poco más largo. ¿Dónde fueron mis salas de trabajo en grupo? La ventana desapareció. Ahí está de nuevo. Vale. Ravi está pidiendo el repositorio. Así que voy a copiar eso en la ventana de chat para él. Y luego voy a abrir las salas de trabajo en grupo durante ocho minutos. Así que puedes hacer este paso y hacer que todo funcione con suspense. Y después de eso, empezaremos a ver cómo podemos trabajar con errores, capturar errores y luego con diferentes formas de orquestar diferentes límites de suspense juntos y los resultados que obtendremos.

9. Límites de Error y Manejo de Errores

Short description:

En esta sección, aprendimos sobre los límites de error en React y cómo manejan los errores en los componentes. Vimos que sin un límite de error, React desmonta toda la aplicación cuando ocurre un error, resultando en una página en blanco para el usuario final. Sin embargo, al agregar límites de error, podemos capturar errores en componentes específicos y hacer que el resto de la aplicación continúe renderizando. También exploramos la anidación de límites de error y los beneficios de hacerlo. Recomiendo usar el paquete npm de límite de error estándar de React, que permite reintentos de error. Por favor, añade límites de error a tu aplicación. A continuación, pasaremos a anidar componentes de suspense.

Bien, entonces suspense. Añadir un límite de suspense es relativamente fácil, pero ¿qué pasa si hay errores? Bueno, si hay errores en un componente normal de React durante la renderización, tenemos un límite de error. Y en suspense, eso realmente no es diferente. Así que no tengo que añadir ningún error code a los componentes individuales que hacen cosas. Simplemente añado límites de error igual que tengo límites de suspense. Y en realidad tenía uno por defecto. Si vuelvo a mi index.tsx, bien, oh, eso no es legible. Justo aquí en la raíz de nuestra aplicación, tenía este límite de error con un componente de fallback que realmente lo muestra. Y no tengo ningún code aquí para hacerlo pero normalmente también tendría code aquí que se aseguraría de que el error se enviaría a un servidor, se recogería allí, y algo como Sentry, etc., se utilizaría para recoger todos los errores. Así podría ir a buscar los bugs y arreglarlos. Y en realidad podemos ver eso si introduzco un error, déjame hacer esta URL inválida de nuevo y vuelvo aquí y me aseguro de que no había data en la caché. Voy a los usuarios, hago clic en el primer usuario, vemos cargando. Vemos esta pantalla de error, que es el resultado de estar en el entorno de desarrollo. Pero en tiempo de ejecución, veríamos esto, bueno, algo salió mal, el texto de estado no se encontró, porque es un 404, no se encontró. Ahora, esto sólo está ahí por el límite de error. Vamos a quitar ese límite de error por un segundo y veamos qué pasa en una aplicación normal sin un límite de error. Y estoy seguro de que todos lo han visto antes. Refrescaremos la aplicación, haremos clic en el usuario. Obtendremos ese mismo 404. Debido al entorno de desarrollo, obtenemos esto de nuevo, pero en tiempo de ejecución, el usuario final llegaría a ver esto, una página completamente en blanco. No muy informativa, no muy útil, pero como no hay un límite de error, React básicamente desmonta toda la aplicación. Si voy a la console en las Herramientas de Desarrollador, en realidad puedo ver que algo salió mal. Y aquí abajo puedo ver la pila completa de componentes que se desmontó porque no había nada manejando esto. No había ningún límite de error manejando esto. Exactamente lo mismo que pasaría con otros errores. Entonces, déjame deshacer esto para que el límite de error vuelva. Y ahora, debería ser capaz de atraparlo de nuevo. Asegurémonos, sí. Ahora, aún así esto no es muy agradable, sólo porque un componente explotó. Es como si todavía desmontara toda la aplicación porque sólo tengo un límite de error. Y eso está justo en la raíz de nuestra aplicación. En realidad, sólo es un componente el que dio error. Bueno, lo bonito de los límites de error, puedo probarlos. Entonces, puedo tomar este límite de error e ir a ese componente de detalles del usuario, que es responsable de los detalles de la cuenta y los detalles de la película favorita. Y podría decir, bueno, quiero un límite de error aquí. Y haré lo mismo alrededor de los detalles de la película. Resuelvo estas importaciones para que compile de nuevo. Y ahora si refresco, así que tengo mi aplicación de nuevo, hago clic en el usuario. Llegamos a la página de error de desarrollo. Pero ahora en realidad veo que, bien, sólo el componente de detalles del usuario dio error y el límite de error alrededor de eso lo atrapó. Pero todos los demás aún se renderizaron, y puedo ir a otro componente o a otro usuario y aún se renderizará. Por supuesto, ese componente de detalles del usuario no se va a arreglar solo, la URL es inválida, así que nunca va a llegar allí, pero potencialmente puedo cerrar ese límite de error y hacer que lo reintente. No se va a arreglar solo, por supuesto, pero con algún otro error, en realidad podría. Podría ser porque la red no estaba disponible. Y ahora, si lo cierro, en realidad vuelve y es capaz de buscar los data. Así que anidar estos límites de error es realmente agradable y realmente útil. Así que ese es el límite de error en la raíz, que ya está ahí, así que no hay necesidad de añadir eso. Pero introduce ese mismo error que acabo de hacer haciendo esa URL inválida. Así que obtienes un 404 no encontrado al intentar buscar un usuario específico. Y luego, añade ese límite de error dentro del componente UserDetails. Y justo aquí, también ves un componente Suspense. No hay necesidad de añadir eso. Eso es en realidad un pequeño error en mi captura de pantalla que es de una etapa posterior cuando había tanto un error de suspense como un límite de error. Sólo añade los límites de error alrededor de los AccountDetails y alrededor de los MovieDetails allí. Así que estos dos. Y luego, deberías ser capaz de atrapar el error alrededor de ese único componente y hacer que todos los demás se rendericen. Y en realidad estoy usando el límite de error estándar de React paquete npm aquí, que es realmente agradable, que en realidad permite que se reintente. Así que si haces clic en esa cruz, en realidad lo volverá a intentar. No creé un límite de error personalizado ni nada. Este es un paquete realmente agradable y muy recomendado para usar en tu aplicación. Así que por favor, ve y añade estos. Voy a abrir las salas de la masterclass durante 5 minutos de nuevo. Después de eso, vamos a echar un vistazo a la anidación de componentes de suspense, al igual que podemos anidar límites de error. Porque en muchos aspectos, trabajan de formas muy similares. Pero ese es el próximo paso. En este paso, vamos a crear ese límite de error anidado y comprobar qué pasa cuando ocurren errores. Así que todos de vuelta. ¿Todos tuvieron éxito con este paso? El límite de error captura errores. Bien. Pulgares arriba.

10. Anidando Límites de Error y Límites de Suspense

Short description:

El componente suspense atrapa las promesas que se lanzan, mientras que el límite de error atrapa los errores. React comienza en el componente que desencadena el suspense y sube por el árbol para encontrar el primer límite de error. La diferencia entre los dos es que el límite de error tiene una propiedad de fallback que potencialmente puede suspender, mientras que el componente suspense está dentro del límite de error. Se recomienda tener un límite de error en la raíz de la aplicación para manejar todos los errores. Anidar límites de error y límites de suspense es útil. Poner un límite de suspense alrededor de la aplicación y un límite de suspense alrededor del componente específico puede mejorar la experiencia del usuario. Sin embargo, es importante considerar el impacto en el rendimiento de la aplicación. Mantener una lista de usuarios y mostrar un spinner para los detalles del usuario se puede lograr anidando componentes de suspense.

Bien, se ve bien. Entonces, en realidad hay dos preguntas. Una de Alexi. Pensé que el componente suspense está atrapando los errores que son lanzados por los hooks u otros componentes hijos. ¿Cómo atraparía el error el componente límite de error si el suspense es su hijo? Los componentes suspense en realidad no atrapan errores. Atrapan promesas que se lanzan. Y si se lanza una promesa, entonces el límite de suspense se activa, incluso si otra cosa lanza un error o algo más, una cadena o un número, pero siempre debes lanzar objetos de error, entonces el límite de suspense lo va a ignorar. Y lo va a dejar al límite de error para manejar eso. Entonces- Eso tiene sentido, la única cosa como si la promesa es rechazada, ¿también se considera como un error? O sí, si la promesa es rechazada, eso es un error y se tratará de la misma manera como si se hubiera lanzado un error en primer lugar. Entonces el límite de error sería capaz de atrapar esto probablemente. Y en ese caso, React comienza en el componente que provoca el suspense y comienza a subir por el árbol para encontrar el primer límite de error desde allí. No desde el componente suspense, sino desde el componente original que inició el suspense.

Y había otra pregunta y solo abriré Discord aquí por un momento para mostrar. La diferencia entre los dos y el primero tiene el límite de suspense y anidado dentro de él está el límite de error y dentro de eso está el componente. Y con dos, tenemos el límite de error en el exterior, suspense dentro de él y los componentes dentro de eso. ¿Hay alguna diferencia entre los dos? Sí. Pero dicho eso, en propósitos prácticos, probablemente no. La única diferencia es, si miras el límite de error aquí, tiene una propiedad de fallback que potencialmente podría suspender. Ahora es bastante improbable que eso suceda, pero si hay un error, podría cargar de forma perezosa diferentes componentes para mostrar eso. No recomendaría hacer eso porque si tienes un error debido a algún problema de conectividad de red, vas a intentar cargar un componente de error que también viene a cargar debido a ese mismo problema de conectividad de red. En ese caso, podría suspender y sería atrapado por este mismo componente suspense. Y aquí es al revés. Si el límite de error tiene algún tipo de razón para suspender con su visualización de error, y no puede porque el suspense es, o debería decir el componente suspense está dentro de él. Pero ahora en caso de que el fallback del suspense, si eso es un error, bueno, el límite de error puede atrapar eso. Lo que normalmente hago es en la raíz de mi aplicación, tengo el límite de error en la raíz misma porque quiero ser notificado de todos los errores que ocurren dondequiera que ocurran. Y normalmente no deberías hacer ningún trabajo asíncrono por lo que al menos no hay nada que suspenda. Si envío data a un servicio de recopilación de errores, no voy a hacerlo inmediatamente allí porque si hay problemas de conectividad, podría no llegar nunca. Así que voy a ponerlo en alguna cola y eventualmente enviaré cosas y almacenaré esa cola en el almacenamiento local o en el índice DB así que incluso si el usuario refresca el navegador, esos errores no se pierden. Podrían eventualmente perderse, pero no en una circunstancia normal. Por supuesto, si el usuario nunca se conecta a internet no lo voy a conseguir pero en circunstancias normales eventualmente conseguiré ese error. Entonces, Martina dice, pero el primer ejemplo es en realidad lo que tenemos ahora en la aplicación porque tenemos un suspense alrededor de la aplicación y el límite de error alrededor de los detalles de error. No del todo, porque también tenemos un límite de error justo en el nivel de índice. ¿Dónde está mi index.tsx? Ahí. Así que aquí, donde renderizo lo primero es un límite de error que es una especie de atrapa todo en caso de un error que no se maneja localmente, será atrapado por eso. Y luego dentro de eso, tengo el límite de suspense que también es una especie de atrapa todo. Aún no hemos hecho suspense anidado pero normalmente suspendería más cerca de donde realmente quiero. Y este es una especie de límite de suspense de último recurso para asegurarme de que mi aplicación no falla. Entonces el límite de error está en el exterior, suspense dentro, y luego potencialmente, o más probablemente tendré versiones anidadas de esos dos dentro de otros componentes donde puedo manejar las cosas localmente. Así que espero que eso aclare esos dos. Pasemos al siguiente paso. Porque como mencioné, podemos anidar límites de error, pero también podemos anidar límites de suspense. Y eso es bastante útil. Porque si vuelvo a mi aplicación por un momento, en realidad comencemos aquí, refrescar para asegurarme de que tengo todo en orden. Refrescar para asegurarme de que no tengo nada en la caché, y veamos qué pasa con una red realmente lenta. Así que lo he configurado para simular una red 3G lenta en este momento, que es bastante lenta. Irrealmente lenta para la mayoría de las aplicaciones, pero ahora si hago clic en usuarios, vemos que toda la página está prácticamente en blanco. La barra de navegación desaparece, y solo vemos ese spinner. Hago clic en el usuario y de nuevo, toda la página está en blanco, y ni siquiera vemos la barra de navegación. Y si vemos una lista de usuarios, ahora si hago clic en el segundo usuario, eso se ha ido, la barra de navegación se ha ido. Entonces eso está bien. Los límites de suspense funcionan. Son atrapados, pero es un poco dramático, y está eliminando demasiado. Entonces lo que podemos hacer es que podemos decir, bueno, vamos a agarrar este límite de suspense y vamos a ver qué hay dentro de esta aplicación. Bueno, aquí podemos ver el navegador del router para React Router, y podemos ver la barra de navegación, así como se manejan las rutas. Bueno, en este caso, no se hacen con lazy, pero es bastante probable que se hagan. Por lo tanto, es bastante probable que esos suspendan. Entonces, poner un límite de suspense alrededor de esto es en realidad un muy buen lugar. Así que vamos a reanudar esas importaciones, y veamos cuál es el efecto. Así que volveremos aquí. Simularé el 3G de nuevo. Vamos a Usuarios, y ahora todavía vemos ese spinner de carga, pero la barra de navegación se queda en la parte superior. Así que hago clic en el usuario, la lista de usuarios desaparece, pero la barra de navegación se queda. Entonces es un poco mejor, pero no del todo bien. Porque ahora si cambio entre usuarios, me gustaría mantener esa lista de usuarios y solo mostrar un spinner aquí para los detalles del usuario. Entonces, dentro de los detalles del usuario aquí, podría decir, bueno, realmente quiero otro componente suspense aquí. Y necesito resolver estas importaciones también. Ahora todo eso está dentro de un límite de suspense. Así que ahora si hago clic en un usuario eso en realidad se queda. Pero es solo, déjame cambiar aquí de nuevo. Hago clic en el usuario y muy brevemente, podríamos disparar el spinner allí.

11. Anidando Límites de Suspense

Short description:

Podemos anidar límites de suspense para lograr una UI decente. React 18 respeta null como el fallback para suspense, a diferencia de React 17. Anidar componentes de suspense nos sirve bien incluso con React 17. Pasemos a suspense en paralelo, que es similar a los límites de error.

Y ahora obtenemos un spinner aquí. Y podríamos decir potencialmente, bueno, quiero ese primer encabezado fuera del suspense. Así que los detalles del usuario aparecen de inmediato. Así que ahora, si hago clic en el usuario, vemos los detalles del usuario, y solo los detalles y la parte de la película favorita que aparece cuando se carga la data. Así que no es exactamente como se veía cuando empezamos, pero es bastante cercano. Y en realidad creo que esta es una forma bastante decente de anidar límites de suspense y obtener una UI bastante decente.

Así que anidando límites de suspense, puedes anidarlos como quieras. Y básicamente cada vez que un componente suspense, React comenzará a recorrer el árbol de componentes. Así que comenzará en el componente que suspense. Miremos a sus padres. Si ese componente suspense, lo usará, si no, subirá uno, etc. Así que localizará el componente de suspense más cercano y lo usará para suspender la aplicación. Si hay varios componentes suspendiendo, cada uno hará este pequeño truco por sí mismos y varios componentes de suspense pueden estar activos al mismo tiempo.

Ahora hay un cambio de comportamiento con React 18. Todavía estamos en 17, así que aún no puedo mostrar eso. Pero con la UI de fallback que especificamos aquí mismo, esta, tengo un componente, un componente de Carga que muestra ese spinner. Podría poner un poco de texto aquí, básicamente cualquier cosa que sería válida para que React la renderice podría entrar allí. Y una cadena es perfectamente válida. Pero React también dice que null es perfectamente válido. Puedo tener un componente que en su render devuelve null y eso significa básicamente que no hay necesidad de renderizar nada aquí. Bueno, si haces eso en React 17, React 17 va a ignorar ese límite de suspense null. Básicamente lo tratará como si no existiera. Y seguirá subiendo por el árbol, encontrará el siguiente. Con React 18, en realidad respetará eso y dirá, está bien, no quieres renderizar nada, entonces está bien, no vamos a renderizar nada hasta que esto se resuelva. Es bastante improbable que te afecte. No he visto ningún code de producción donde la gente use null como el fallback para suspense, pero es posible y es un cambio de comportamiento.

Así que aquí fue el primer límite de suspense que agregué, el primero anidado, y luego tuvimos este resultado. Y luego entré en el componente de detalles de la película y agregué un límite de suspense más allí. Y obtuvimos este resultado cuando empezamos a hacer clic en Usuarios, que, sé que la UI no siempre es una gran herramienta, no soy realmente un experto, pero me gusta bastante este resultado y sirve bastante bien en las aplicaciones. Así que incluso con React 17, anidar estos componentes de suspense nos sirve realmente bien. Así que vamos a hacer esto. Es otra tarea de cinco minutos. Así que voy a abrir la sala de breakout en cinco minutos de nuevo. Antes de hacer... Hubo un par de preguntas más. Así que de Raffy... Así que se recomienda el dos, supongo que te refieres a aquí en Slack. Así que ese es el que recomiendo. Y este ya lo respondí. Vale. Así que déjame abrir las salas de breakout y nos vemos a todos aquí en cinco minutos. Así que todos están de vuelta de nuevo. Todos tuvieron éxito con este paso en el siguiente límite de suspense funcionando. Estaba obteniendo un error, en realidad, pero no sé, como, por qué es eso, como en los detalles del usuario, componente de lista de usuarios, estoy obteniendo un error en la línea donde estamos tratando de iterar sobre data. ¿Esta línea? Sí. Sí. El signo de interrogación solucionó este error, pero no estoy seguro de por qué estamos obteniendo indefinido aquí porque como estamos usando suspense. Como esto. ¿Estás obteniendo un error de compilación, no un error en tiempo de ejecución? No, en tiempo de ejecución. ¿En tiempo de ejecución? Sí. En tiempo de ejecución, eso no debería ser el caso. Sí, ese era el problema. Como, sí, poner un signo de interrogación aquí significa que funcionará, pero incluso un signo de exclamación, que simplemente le está diciendo al compilador, como sé que data nunca está indefinido, trátalo como un objeto, está bien, es realmente una matriz, confía en mí. Eso no es una comprobación en tiempo de ejecución. Eso es realmente común. Probablemente solo me equivoqué con el suspense en algún lugar en la parte superior, tal vez. Sí, simplemente no lo sé. Parece que funcionó. Lo que podrías querer comprobar es aquí, si tienes este suspense allí en la configuración de SWR. No. Esa es la pieza que me falta, en realidad. Sí, gracias. Sí, suspense. Vale, resuelto. Gracias. De nada. Así que, hagamos suspense en paralelo porque hicimos límites de error en paralelo y he mencionado un par de veces que suspense y límites de error son realmente similares entre sí y realmente hacen lo mismo excepto que uno lo hace por una promesa lanzada y otro lo hace por un error lanzado. Pero aparte de eso, son, bueno, no exactamente lo mismo obviamente, pero muy cercanos en la forma en que trabajas con ellos. Y tuvimos que, ¿dónde estaba mi code? Y eso son detalles de usuario. Tenemos límites de error aquí en paralelo, pero solo tenemos un solo suspense.

QnA

Suspense en Paralelo y Manejo de Preguntas

Short description:

Podemos agregar suspense en paralelo duplicando componentes de suspense para diferentes detalles. Sin embargo, la interfaz de usuario puede no ser perfecta, y React 17 no proporciona mucho control sobre las suspensiones independientes. Con React 18, tendremos componentes de lista de suspense que coordinan múltiples límites de suspense y permiten un mayor control sobre la renderización y resolución. Después del descanso, se hizo una pregunta sobre cómo hacer compatible una capa de red existente con suspense, y se mostró una demostración de lanzamiento de promesas en código personalizado.

Bueno, ¿por qué no podemos agregar eso en paralelo? Bueno, podemos. Puedo simplemente duplicar estos. Así que tengo el suspense alrededor de los detalles de la cuenta y tengo un suspense diferente alrededor de los detalles de la película. Y ahora si vuelvo a la aplicación, asegurándome de que nada está bien, obtenemos dos spinners de nuevo si hago clic en el usuario. Uno para la película, su película favorita, uno para sus detalles de usuario. Cada uno se suspende independientemente del otro y cada uno se reanuda independientemente del otro. Y al igual que antes, si hago el suspense dentro o fuera del límite de error, déjame cambiar uno de ellos, no importa. Es solo cuestión de, bueno, si este fallback lanza un error, entonces este límite de error puede atraparlo. Y aquí, si este componente de fallback suspende, entonces este suspense puede atraparlo. Pero como mencioné antes, probablemente no sea la idea más sabia. Aquí, realmente no me importa cuál es el orden, cuál anidas dentro del otro, en la raíz de mi aplicación, creo que el límite de error siempre debería ir afuera. Aquí, no es tan importante. Y todavía van a funcionar exactamente de la misma manera. Ahora esto funciona, y es realmente agradable, pero una cosa que personalmente no me gusta de la UI, pero de nuevo, no soy un experto en UI. Como dije antes, es el resultado de la película favorita primero. Entonces, vemos dos spinners. Luego vemos el spinner de Detalle de Usuario, nuestra película favorita con los detalles reales. Y luego User Detail Resuelve sus data. Entonces, la película favorita en realidad se empuja hacia abajo. No me gusta eso desde el punto de vista de la UI. Que pueda hacerlo, que tenga la capacidad de organizarlo de esa manera, es realmente agradable. Que la UI funcione de esa manera, meh, no estoy tan contento con eso. Pero en este caso, en realidad lo hice intencionalmente. Puede que lo hayas notado, pero si entramos en estos componentes. En la URL, tengo un servicio aquí donde puedo especificar un sueño específico. Entonces, cada detalle de la cuenta va a esperar un segundo antes de responder. Y cada detalle de la película aquí va a esperar medio segundo antes de su respuesta. Entonces, siempre va a responder más rápido. Hice eso intencionalmente para mostrar exactamente este comportamiento de los dos usuarios y los data siendo empujados hacia abajo. En la aplicación real, no sabes cuál es el orden. Y a veces, el primero se resolverá, a veces el segundo. En una máquina de desarrollo, normalmente van a responder bastante rápido porque normalmente ejecutas cosas localmente y todo es rápido en producción. Va por internet o tal vez alguna red de la empresa, pero las cosas probablemente van a ser más lentas y no tan bien. Con React 17, realmente no hay mucho que podamos hacer al respecto. Ambos componentes de suspense van a ser independientes entre sí. Van a hacer su propio suspense. Van a hacer sus propias reanudaciones, y eso es todo. No obtenemos más control. Lo único que podemos hacer es decir, bueno, no quiero este comportamiento. Entonces, pon un límite de suspense alrededor de ambos componentes que suspenden. Cuando lleguemos a React 18, veremos los componentes de lista de suspense, y el componente de lista de suspense coordinará múltiples límites de suspense como este, y obtenemos control sobre cómo reaccionarán o cómo se renderizarán juntos y cuándo se resolverán, lo cual es realmente agradable. Pero con React 17, aún no tenemos exactamente eso. Entonces, el suspense en paralelo. El cambio que hice, en este caso, solo tengo suspense, pero los límites de error pueden permanecer allí como acabo de tener en mis componentes. Básicamente, haz que se suspendan en paralelo, y tenemos este resultado, que funciona bastante bien, excepto en este caso, la forma en que se desplaza la UI no es exactamente perfecta. Pero lo solucionaremos cuando instalemos React 18.

Hola, todos de vuelta del descanso. Tiempo para continuar. Antes de continuar, Alexei hizo una pregunta interesante en la ventana de chat en Zoom. Estamos usando el gancho use SWR para proporcionar una API de fetch compatible con suspense para nuestros componentes, pero ¿qué pasa si ya tuviéramos una capa de red en nuestra aplicación existente? ¿Cómo podríamos hacerla compatible con suspense? ¿Vamos a pasar por eso? Bueno, no planeaba hacerlo, pero puedo hacerlo brevemente. No voy a crear una biblioteca completa. Y la segunda parte que me intriga sobre las API de bajo nivel de la característica de suspense, cómo puedes lanzar promesa en tu propio code. Y en realidad puedo mostrar eso relativamente fácil. ¿Dónde está mi aplicación aquí? Entonces, veamos qué pasa si lanzo suspense. Supongamos que estoy en los detalles del usuario aquí y agreguemos un botón en la parte superior. Suspéndeme o algo así. Y tenemos un clic. Oops. Y ahora necesitamos hacer algo aquí. Así que tendremos un manejador de eventos y lo mantendré simple en línea. Ahora, esto necesita renderizar o esto necesita suspender cuando renderizamos. Así que realmente no puedo hacerlo aquí en este clic directamente porque entonces estamos en un manejador de eventos y no estamos renderizando realmente. Así que necesito introducir un poco de estado. Así que haremos const suspend me. Escribir es difícil. Nuevos estados y comenzaremos con falso. Y luego aquí dijimos suspend me a verdadero. Ahora, por supuesto, eso no hace nada todavía. Entonces, si abro un usuario, tenemos suspend me y puedo hacer clic en él, no pasa nada. Bueno, algunos cambios de estado, pero no estamos usando ese estado, pero ahora puedo usar este estado.

Suspender e Instalación de React 18

Short description:

Exploramos cómo suspender un componente utilizando una nueva promesa. Al lanzar una nueva promesa, podemos suspender el componente. Resolver la promesa después de un tiempo de espera resuelve la suspensión. Esta técnica se puede utilizar en cualquier función llamada desde el ciclo de renderizado. Mover el código fuera del ciclo de renderizado, como en un manejador de eventos, no causará suspensión. Luego cambiamos a React 18 y discutimos el proceso de instalación. La última versión de React 18 se puede instalar usando npm, y hay diferentes etiquetas disponibles, incluyendo 'latest' y 'next' para la versión alfa.

Y aquí podría ver algo como si me suspendes, lanza una nueva promesa. Y eso realmente hará que este componente se suspenda. Y eso se queja porque necesita una función de devolución de llamada. y lo dejaremos vacío por ahora. Así que ahora si abro el usuario y hago clic en suspéndeme, hemos suspendido realmente nuestro componente.

Ahora esta promesa nunca se resuelve o rechaza. Así que esto permanecerá suspendido para siempre. Así que vamos a resolverlo. Así que el constructor de promesas toma una función que obtiene una función de resolución y rechazo, pero solo voy a resolverlo por ahora. Así que haremos un setTimeouts y llamaremos a esa resolución después de decir dos segundos. Así que ahora si hago clic en el botón de suspensión, en realidad necesito establecer la bandera de suspensión en falso, de lo contrario se volverá a renderizar e inmediatamente se suspenderá de nuevo. Así que volveremos a establecer la bandera de suspensión en falso y volveremos a renderizar. Y en realidad, ¿quiero hacer eso aquí? Creo que esto debería estar bien. Comprobemos. Así que tenemos useDetailsLoaded, está suspendido y después de dos segundos, esperaba que se resolviera, pero aparentemente no lo hace. Entonces, ¿por qué es eso? Quizás necesito hacer esto primero. Comprobemos. ¿No deberías invocar para resolver? En realidad estoy haciendo eso. Puedo hacerlo explícitamente, pero debería estar haciendo eso pasando la referencia de la función al setTimeout. Eso debería ser lo mismo, pero comprobemos. Quizás eso es en realidad la diferencia. ¿Deberíamos establecer esto dentro de esta devolución de llamada? ¿Establecer el suspendMe dentro de la devolución de llamada? Así que después de un tiempo de espera, como después de 2000 milisegundos, deberíamos establecer suspendMe en falso. ¿Aquí, quieres decir? Sí, sí, sí, dentro de esa devolución de llamada. Eso parece razonable. Veamos si eso lo arregla. Así que se suspende. Eso era. Gracias. Así que ahora se suspende. Espera dos segundos, y luego se resuelve. Así que el núcleo de suspense es realmente muy simple. Es solo esto, lanza una nueva promesa. Y con eso, bueno, eso no es específico de react. Podrías hacer esto en cualquier lugar. Podrías hacer esto en el hook. Podrías hacer esto en la biblioteca. Puedo poner esto en cualquier función que quiera. Es solo cuestión de que tiene que ser llamado desde este render. Si muevo todo esto code a ese manejador de clics, me deshago de esto por un segundo. Ahora no va a hacer nada. De hecho, eso ni siquiera funciona. ¿Por qué... Tengo un corchete de más, creo. ¿No? Tenías un corchete de menos. Oh, bien. Gracias. Así que ahora no va a hacer nada. ¿Ves? Sin suspensión, nada. Porque no se hace en la renderización. Está en un manejador de eventos. Así que si muevo esto de vuelta, solo copio todo, y establezco el suspend me de nuevo, entonces debería estar bien. Suspende durante dos segundos, y vuelve. Así que con eso, realmente no es tan difícil construir en bibliotecas existentes. Solo tienes que asegurarte de que estás dentro del ciclo de renderizado, y con un hook, eso es fácil. Lo dejaremos así.

¿Dónde están mis diapositivas? Ahí. Así que con eso fuera del camino, vamos a cambiar a React 18, y vamos a echar un vistazo a lo que React 18 nos trae, tanto con estos límites de suspense, como con ese componente de números primos, que es realmente lento y torpe. Pero por supuesto, lo primero que tenemos que hacer es que tenemos que instalar React 18, y si miramos en npm, Este es el paquete de React, pero con React DOM, vería exactamente lo mismo. Puedo ir a versiones. Y aquí, verás que hay diferentes versiones. Ahora tenemos aquí una etiqueta última. Esa es la versión normal que usas cuando haces npm instalar de React. También está esta versión con la etiqueta next, que actualmente apunta a 18.0 alfa, que desde hash, y luego está esta fecha del 23 de octubre. Y es el 27 ahora, así que hace cuatro días. Pero en realidad fue lanzado dice aquí hace dos días. Así que creo que fue el último viernes o así y lanzado el lunes. Ahora mismo, también está esta alfa y versión experimental. Y alfa y next son en realidad la misma cosa. Experimental es diferente. En realidad, esa también es la misma versión, que puedes decir por este hash.

Instalando React 18 y Actualizando el Código

Short description:

Para instalar React 18, use la rama 'next' con la etiqueta next. Use 'npm install React-at-next' y 'React-dom-at-next' con la bandera '--force' para instalar las dependencias. React Router DOM 6 es compatible con React 18 y React 17. La API del router ha cambiado, ahora se basa en hooks. Use el hook 'useRoutes' para definir las rutas. React DOM.render ya no es compatible en React 18, use React root en su lugar. Actualice el código para usar 'createRoot' y pase el elemento DOM como parámetro. TypeScript puede mostrar un error de compilación, pero se puede solucionar utilizando el signo de exclamación para afirmar el tipo de 'getElementById'.

Todavía tiene el mismo hash, pero no tiene la versión 18.0.0. Así que en este momento, estas tres cosas dan lo mismo. El objetivo aquí es que next debería convertirse eventualmente en la versión más estable de los candidatos a la versión de React 18, etc. Alpha siempre será algo menos estable, y Experimental básicamente serán compilaciones diarias. Así que si estás buscando la próxima versión a ser lanzada, la rama next aquí es la que te interesa para lanzar con la etiqueta next. Así que podemos ir e instalar eso. Ahora, si simplemente haces una instalación MPM de React-at-next y React-dom-at-next, en realidad fallará debido a las dependencias. No estoy 100% seguro de cuál es el caso. Pero con un dash dash force, en realidad funcionará. ¿Dónde está la consola allí? Así que vamos a limpiar esto. MPM instala React-at-next y React-dom-at-next con dash dash force. Así que eso debería instalarse bastante rápido porque esos paquetes son en realidad bastante pequeños. Así que esos están instalados. Y por ejemplo, puedes ver con SWR. Dice que quiere React 16.11 a 17. Así que esa es una de las bibliotecas que en realidad se quejaría y rechazaría la instalación sin un dash dash force. Otra biblioteca que podría ser potencialmente un problema. Si voy al paquete de JSON, puedes ver lo que tengo. Tengo React router DOM aquí. El router de React comúnmente utilizado. Ahora si usas la versión normal, la versión cinco, no es compatible con React 18. Así que en realidad estoy usando la versión beta de React router DOM 6, que es compatible con React 18. Y como ya hemos notado, también es compatible con React 17. No estoy seguro de cuál es la última, la versión más temprana para React router DOM 6, pero va a React 16 algo. Así que las versiones relativamente recientes de React funcionarán perfectamente bien con él. Ahora la API ha cambiado. No es realmente parte de la presentación, pero aún así es útil verlo. Quería ir aquí, ruta de la aplicación. El router ahora se basa en hooks. Así que ahora hay un hook de useRoutes que pasas en un array de las diferentes rutas y las diferentes opciones. Como aquí estoy diciendo para usuarios usar el elemento, lista de usuarios y para primos usar números primos. Y para el inicio, solo tengo algo de marcado en línea aquí. Así que ha cambiado un poco. Reactor router dom cinco no funcionará, al menos no completamente con react 18. Así que ten cuidado con esa actualización. Pero eso es reactor router o más bien react y react dom instalados. Vamos a iniciar la aplicación de nuevo y ver si todavía funciona. Cargando punto punto punto. Y allí vemos parling building en Londres de nuevo. Y vemos usuarios y todo eso todavía funciona. ¿Funciona el límite de suspense? ¿Esto todavía funciona? Sí, eso funciona. Los números primos todavía funcionan con números algo más grandes. Todavía es lento. Así que parece que nuestra aplicación funciona pero realmente no ha tenido ningún efecto significativo, observable. Ahora esto, hasta que voy a las herramientas de desarrollador. Si abro el registro de la consola y lo pongo en no throttling, es el que quería, la consola. Aparece un mensaje aquí. Advertencia, React DOM.render ya no es compatible en React 18, usa React root en su lugar. Hasta que cambies a la nueva API, tu aplicación se comportará como si estuviera funcionando en React 17. Así que aunque no es compatible, funciona pero realmente no estamos utilizando ninguna de las capacidades de React 18. Actúa como si fuera React 17. Bueno, eso no es lo que queremos. Así que vamos a solucionar eso. Así que volveremos al index.tsx. Aquí, tenemos nuestro React dom.render, que no deberíamos usar. Dice usar.createRoot. Y React dom.createRoot devuelve un objeto y todavía tiene una función de renderizado. Así que se convierte en algo como esto, excepto que el elemento DOM en el que queremos renderizar se convierte en parámetro para createRoot. Así que se ve así. Lo único es que hay un error de compilación aquí. Tipo null no asignable a elemento o documento o fragmento de documento o comando. La razón es que createRoot si miro la escritura está tipada como uno de esos parámetros pero no null o undefined. Esa no es una opción válida. Y si miro getElementById. Devuelve un elemento HTML o null porque si especificas un ID que no existe, getElementById no lanza un error. Simplemente devuelve null. Sabemos que este elemento existe así que TypeScript arreglado el signo de exclamación diciendo TypeScript, yo sé mejor. Yo sé un mejor tipo. TypeScript, yo sé mejor. Yo sé que getElementById siempre devuelve un elemento HTML no un null.

Renderizado de React 18 y Nuevos Hooks

Short description:

Estamos utilizando el renderizado de React 18, pero la aplicación sigue siendo lenta. React 18 introduce nuevos hooks, incluyendo useDivertValue, useTransitionHook, useMutableSource y useOpaqueIdentifier (o useID). useOpaqueIdentifier es útil para enfocar automáticamente los campos de entrada asociados con las etiquetas. Puede ser desafiante lograr este comportamiento cuando se renderiza tanto en el servidor como en el lado del cliente, pero useOpaqueIdentifier simplifica el proceso. Tenga en cuenta que useOpaqueIdentifier puede ser renombrado a useID en la versión actual de React 18.

Y ahora estamos felices de nuevo. Y ahora si vuelvo a la aplicación y la refresco, no hay más errores en la console. Se renderiza bien. Y estamos utilizando el renderizado de React 18 y todo. Dicho esto, esto sigue siendo lento. Estamos utilizando concurrent rendering, pero realmente aún no podemos decirlo porque aún no estamos aprovechándolo, pero lo estamos utilizando. Así que aquí están las actualizaciones al package.json. Tengo versiones un poco más antiguas aquí. Las versiones se lanzan bastante a menudo, pero eso no debería, al menos espero porque sé que hay un cambio en el code del que hablaré cuando lleguemos allí, pero eso no debería afectarnos, espero. Entonces, la adición, el cambio al index.tsx a react-dom.createRoot. Ahora, si estás en TypeScript, te preguntarás cómo es que esto compila y funciona, porque createRoot no existía en React 17. Bueno, tengo este archivo tsConfig, que obtienes por defecto si creas una aplicación de React utilizando la opción //template TypeScript, pero le añadí una cosa, y es esta línea. Los typings de react-dom y react no están incluidos con el paquete MPM original, vienen de DefinitelyTyped. Y por defecto, mirará los typings estándar allí, pero los typings de DefinitelyTyped contienen la próxima versión. Así que ya le dije a TypeScript que mire estas próximas versiones de React, por lo que ya sabe que la nueva API existe. Por eso no obtuve un error de compilación allí. Eso se añadió previamente. Pero si creas una nueva aplicación o de una aplicación existente, vas a actualizar a React18 antes de que sea lanzado, entonces estos tipos no serán actualizados, entonces tendrás que hacer lo mismo. Pero ahora eso ya está hecho, así que no hay que preocuparse por ello. Así que el cambio allí. Y por favor, ve y hazlo. Así que React18 en realidad nos da bastantes características nuevas. Los nuevos hooks, hay un montón de cosas de renderizado del lado del servidor que mencioné que no vamos a mirar, pero el renderizado del lado del servidor con suspense ahora es posible. Pero los nuevos hooks son bastante interesantes y voy a mirar algunos de ellos. Hay uno nuevo llamado useDivertValue que puede ser útil en escenarios de performance. Ahora no vamos a usar eso. En realidad no ayuda mucho con esos números primos pero ese es el tipo de caso donde podría potencialmente ayudar. En este caso, simplemente es demasiado lento y usar DivertValue no lo arreglará. Pero lo que DivertValue básicamente te permitirá hacer es decir, hay un valor que cambia frecuentemente y no me importan todos los cambios. Solo dame algunos cambios y dame el valor final cuando se calme. Si miras la documentation para la próxima versión de React, todavía está un poco anticuada. Dice que hay un parámetro allí donde puedes especificar cuánto puede retrasarse eso no existe en la base de code actual. Así que la documentation está un poco equivocada allí y realmente no hay mucho que puedas configurar. Empujas un valor, que cambia frecuentemente y obtienes un valor. Hay un useTransitionHook que es muy útil para las transiciones de estado y lo usaremos para un par de escenarios diferentes. Así que lo dejaré para más tarde. Hay un nuevo hook llamado useMutableSource que no está realmente destinado para los desarrolladores finales o desarrolladores de aplicaciones. Está más destinado para los desarrolladores de bibliotecas como Redux, MobX, ese tipo de cosas. Y está destinado a prevenir el desgarro de UI. Ahora volveré más tarde y explicaré qué significa el desgarro de UI y cómo eso puede suceder con React 18 porque eso es algo que antes no podía suceder. Y luego el nuevo hook useOpaqueIdentifier o tal vez se llama useID. No estoy muy seguro todavía porque cuando creé estas diapositivas todavía se llamaba useOpaqueIdentifier pero también tenía un prefijo inestable y anunciaron la semana pasada que lo estaban renombrando a useID y eliminando ese prefijo inestable. Así que no estoy cien por ciento seguro de lo que está en la versión actual de React que acabamos de instalar si ya ha sido renombrado allí o que aún no lo ha sido, pero ese es el hook con el que vamos a jugar primero. Y déjame mostrarte dónde querrías usar eso. Si vuelvo a la lista de usuarios tenemos un poco de un formulario de entrada aquí. Ahora, estos campos están desactivados, pero pueden enfocarse. Y puedes ver que hay una barra de enfoque alrededor de ella. Esto es estilización estándar de bootstrap por cierto. Ahora, bastante a menudo en un formulario de HTML, si haces clic en la etiqueta asociada con una entrada, como estoy haciendo clic en apellido ahora, entonces la entrada asociada con eso se enfocará. Pero eso no sucede aquí. Podría conectarlos manualmente, pero eso es un poco tedioso. Y te gustaría hacer eso automáticamente. Ahora, eso no era particularmente difícil de hacer con un hook personalizado en React siempre y cuando todo se renderizara del lado del cliente. Pero si querías hacer eso del lado del servidor y luego hacer exactamente lo mismo del lado del cliente de nuevo, para que fuera consistente y no tuviera que desmontar, remontar componentes o volver a renderizarlos innecesariamente, resultó ser bastante complicado. Bueno, eso es exactamente lo que hace useOpaqueIdentifier. Así que si voy a los componentes en cuestión y vamos a las entradas de etiquetas, podría decir algo como crearé un id aquí y por ahora lo crearé fijo. Es el id de la cadena. Y con la etiqueta hacemos un HTML4 para ese id. Y con un signo igual allí, esa entrada tiene un id. Así que ahora están asociados y deberíamos obtener ese comportamiento de enfoque. Así que si hago clic en el primer nombre, el primer nombre se enfoca. Excepto si hago clic en otro lugar, hago clic en la dirección de correo electrónico tiene el mismo id por lo que todavía establece ese primer nombre en foco. Así que en lugar de este código duro, ahí es donde queremos usar ese identificador opaco. Así que, veamos si eso todavía funciona como lo hizo la semana pasada. Así que importo el uso de identificador opaco con el prefijo inestable y lo llamo o no parámetros ni nada y luego asegurémonos de que esto se refresca. Si hago clic en el primer nombre, el primer nombre se enfoca. Si hago clic en apellido, el apellido se enfoca, correo electrónico, título, etc., excepto con la descripción general porque esa es el área de texto pero podríamos hacer exactamente lo mismo allí. Así que, bastante simple. Pero recuerda, esto será renombrado es bastante posible que se haya roto ahora mismo. Espero que si hago los mismos pasos de nuevo la próxima semana, entonces es casi seguro que se romperá y tendré que usar el hook useID en lugar de useOpaqueIdentifier.

Uso del Hook useOpaqueIdentifier

Short description:

El hook useOpaqueIdentifier en React 18 proporciona un ID opaco, que es una cadena sin ningún significado. Es útil para el renderizado del lado del servidor y se recomienda su uso en tales casos.

Que para ser honesto es un poco complicado. ¿Usar identificador opaco, vaya, por qué opaco? La razón por la que se llama opaco es porque no deberías darle ningún significado a ese ID. En realidad es una cadena pero la cadena en sí misma no tiene un significado. No deberías analizarla. Es solo un ID. Aún así, es una pequeña cosa pero útil especialmente si haces renderizado del lado del servidor. Si no haces renderizado del lado del servidor y tienes algún tipo de hook para generar IDs como este, simplemente quédate con eso. No hay necesidad de cambiar inmediatamente. No es que esto vaya a ser mejor. Pero si estás haciendo renderizado del lado del servidor entonces este es definitivamente el hook recomendado para usar allí.

Uso del componente Suspense List

Short description:

Podemos usar el componente suspense list para controlar múltiples límites de suspense y personalizar su visualización, resolución y componentes de fallback. Al especificar el orden de revelación como 'juntos', los componentes de suspense dentro de la lista de suspense se resolverán simultáneamente, resultando en una mejor experiencia de usuario. La opción 'adelante' nos permite decidir cómo manejar los componentes restantes, con el valor 'oculto' ocultándolos. Al agregar una clave al componente, nos aseguramos de que siempre se vuelva a montar, proporcionando un comportamiento consistente. La lista de suspense es una valiosa adición para gestionar los límites individuales de suspense y controlar su interacción.

Así que el pequeño cambio a labeled input y los dos conjuntos de props para el input y la etiqueta y los resultados donde se enfoca. Si quieres ser completo también estaba, ¿dónde está? Componentes de área de texto etiquetados. Podrías hacer exactamente el mismo cambio allí también. Pero por supuesto, eso es más de lo mismo, así que es algo opcional.

Vale. Así que, como dije, el siguiente paso vamos a echar un vistazo a cómo podemos orquestar diferentes límites de suspense usando un nuevo componente, el componente suspense list. Y suspense list es bastante ordenado. Te permitirá controlar un número de diferentes límites de suspense y te dará una serie de opciones sobre cómo se muestran, cómo se resuelven y qué componente de fallback debería ser renderizado o no renderizado. Al igual que suspense, puedes comenzar a anidar componentes de suspense list, etc. Así que es igual de flexible.

Ahora, vamos a usarlo realmente para deshacernos de este problema donde si hago clic en usuario, vemos dos spinners y siempre se resuelven en el orden de abajo primero y luego el de arriba lo que significa que la UI salta un poco. Esa película favorita es empujada hacia abajo cuando se resuelven los detalles del usuario. Así que lo que podemos hacer es aquí, podríamos agregar un componente de suspense list. Déjame ponerlo aquí abajo. Y vamos a añadir el final de suspense list. y ahora mismo, eso en realidad ni siquiera va a hacer una diferencia. Lo añadí pero vemos exactamente el mismo comportamiento que antes. Si no lo configuras, realmente no obtienes nada más. Hay dos propiedades con las que trabajar. Lo más importante es el orden de revelación y eso puede tener tres valores diferentes, hacia atrás, hacia adelante o juntos. No estoy seguro de cuándo usaría hacia atrás pero hacia adelante o juntos son realmente útiles. Así que si digo que juntos, obtenemos algo, lo que creo que es un comportamiento bastante agradable. Hago clic en el usuario, vemos dos spinners pero ahora en lugar de que la película favorita se resuelva primero y los detalles del usuario se resuelvan después de eso empujando la película favorita hacia abajo, en realidad se resuelven exactamente al mismo tiempo. Lo que hace suspense list si especificas juntos, básicamente esperará hasta que todos los componentes de suspense dentro de la lista de suspense se hayan resuelto y sólo cuando todos se hayan resuelto se resolverán realmente. No es como si uno se resolviera antes que el otro. Así que los combina, lo cual es agradable. Obtenemos dos spinners al mismo tiempo. Cuando el último está hecho, ambos desaparecen y la UI se renderiza. Lo cual es mucho mejor que lo que era antes. Otra opción que podemos hacer es hacia adelante, para palabras con una S. En ese caso, podemos decidir qué queremos hacer con el resto, hay una opción de cola y eso toma dos valores, colapsado u oculto. Primero tomaré oculto, que es el que yo no soy un gran fanático, pero ciertamente tendrá sus usos. Ahora, si hago clic en el usuario, puedes ver que aparecen los detalles del usuario, pero debajo de eso, nada. Déjame hacerlo de nuevo. Nada. Pero cuando hago clic en el segundo usuario, se comporta de manera ligeramente diferente. Ahora vemos spinners de carga y se resuelven al mismo tiempo. Así que, es cuando el componente se monta por primera vez, se comporta de una manera, pero cuando se refresca y se suspende mientras está montado, se comporta de una manera ligeramente diferente. No estoy seguro si esto es un error o no, pero no es lo que yo querría en la UI. Así que, lo que normalmente hago en casos como ese, me aseguro de que siempre esté montado. Y eso es realmente bastante simple. Aquí, estoy en el componente que renderiza esa lista y el detalle del usuario que está seleccionado. Si usas una clave allí, que normalmente se hace en listas de elementos, pero eso funcionará en cualquier componente. Si especificas una clave y esa clave cambia, significa que la instancia del componente, esos detalles del usuario serán desmontados y se montará uno nuevo. Así que, ahora tengo el comportamiento que obtenemos nuevos componentes de detalles de usuario con cada usuario. Así que, obtenemos el mismo comportamiento. Ves que los detalles del usuario aparecen primero, la película siempre después de eso, a pesar de que la película favorita se resuelve más rápido. Pero no hay spinners, no hay UI de fallback. La UI de fallback no existe porque esa cola está oculta. También puedo hacer colapsado. Y esto hará casi lo mismo, excepto que muestra el primer comportamiento de fallback. Así que, ahora vemos un spinner en los detalles del usuario, y cuando eso se resuelve mostró UI, vimos el spinner en las películas favoritas. Así que, un spinner, otro spinner, que es un poco raro si consideras que la película favorita es en realidad más rápida, se resuelve antes que el usuario. Se resuelve antes que los detalles del usuario, pero aún así ese spinner aparece. Pero, dado que aparece de arriba a abajo, la UI es mucho más fácil, las cosas no se empujan hacia abajo. Se llena de arriba a abajo. Podrías hacer lo mismo con hacia atrás, pero eso no es tan agradable. Ahora vemos un spinner, luego vemos las películas favoritas, y luego vemos que se empuja hacia abajo con los detalles del usuario. Estoy seguro de que hay buenos casos cuando esto se aplicaría, pero en la mayoría de los casos, no lo haría. En realidad creo que juntos funciona mejor. Y, como puedes ver en el error de compilación, si usas juntos, la opción de cola no se supone que se use. Porque no hay cola, trabajan juntos. Así que dos spinners resolviendo exactamente al mismo tiempo. Y eso es realmente todo lo que hay en la lista de suspense, pero esa es la pieza que falta con los límites individuales de suspense donde no puedes controlar cómo trabajan juntos. Ahora, con suspense list, puedes, al menos hasta cierto grado, pero las cosas normales que querría hacer, puedo hacer. Así que estoy bastante contento. Solo que como con algunos valores, la primera vez que se renderiza y se vuelve a renderizar se comportan de manera ligeramente diferente, pero si eso es un error o no, no estoy 100% seguro, pero lo arreglé añadiendo una clave a ese componente. Así que se vuelve a montar cada vez y obtengo el mismo comportamiento cada vez. Así que aquí está el cambio que hice. Y lo agradable en este caso, añadí la lista de suspense en el mismo componente que el suspense, pero podría añadir esto en algún lugar más arriba y aún así afectaría a estos suspense.

Renderizado Concurrente y Modo

Short description:

React 18 introduce el renderizado concurrente, que permite renderizar en fragmentos y proporciona pequeñas porciones de tiempo para que el tiempo de ejecución de JavaScript ejecute tareas importantes. No es multihilo, pero coordina el modo concurrente donde React permite que alguien más ejecute entre fragmentos de renderizado.

No tiene que ser un padre inmediato. Simplemente subirá de nuevo al árbol de componentes y React encontrará la primera lista de suspense si está allí y usará esa configuración para trabajar. Así que es bastante agradable. Así que esa adición y el resultado. Así que por favor, añade el componente de lista de suspense, juega con los diferentes ajustes, ve cómo se comporta, lo que te gusta, lo que no te gusta y lo que tiene sentido en el tipo de aplicaciones.

De todos modos, la otra gran cosa que tenemos son los modos concurrent. Ahora, ¿por qué React añadió el modo concurrent? ¿Qué nos da realmente? Si miramos a React 17 y tenemos un montón de componentes renderizando, lo que sucede parece algo así. A la izquierda tenemos algún estado cambiando y luego a la derecha, el modelo de objeto de documento actual en el navegador siendo actualizado y todos los cuadrados azules son componentes haciendo sus cosas de renderizado. Y JavaScript siendo lo que es, de un solo hilo, entonces si hay mucho code ejecutándose y ocurre algún evento externo, no puede hacer mucho al respecto excepto ponerlo en cola.

Así que con React 17, eso es exactamente lo que sucede. Si los componentes están renderizando y hay un evento, aquí dice evento de clic, un usuario hace clic, pero eso podría ser igualmente bien una solicitud Ajax completando o un set timeout o un set interval completando algún tipo de evento externo, entonces JavaScript no tiene más opción que poner eso en cola hasta que lo que se está ejecutando esté hecho. Y en el caso de React, eso significa que todas esas renderizaciones se han ejecutado, el reconciliador se activa, compara el DOM virtual, que fue el resultado de la renderización con el DOM real, hizo cualquier actualización allí, y luego termina y dice, vale, JavaScript, a ti, ¿tenías algo más que querías ejecutar? Y luego JavaScript entra y dice, oh, sí, por cierto, tengo este evento de clic, que cambia completamente todo, así que por favor ve y vuelve a ejecutar toda esta renderización de nuevo. Algo derrochador, pero JavaScript, siendo un entorno de un solo hilo, realmente no puede hacer nada más, no puede ejecutar en paralelo, no sucede.

Ahora con React 18, con el renderizado concurrente, todavía no obtenemos multihilo, JavaScript no lo tiene, React no puede cambiar eso, pero lo que puede hacer es que puede empezar a renderizar en fragmentos, y aquí puedes ver diferentes fragmentos, así que tenemos nuestro cambio de estado, y tenemos unos pocos componentes renderizando, y luego tenemos unos pocos más componentes renderizando, y luego unos pocos más, etc., pero entre esos, aquí y aquí, y los otros descansos, son pequeñas porciones de tiempo, donde React principalmente dice, tiempo de ejecución de JavaScript, ¿por casualidad tenías algo importante que querías ejecutar, bien, ahora es tu momento, adelante, así que no es multihilo pero es coordinado, modo concurrent, donde básicamente dejas que alguien más entre en medio.

Estado de React y Renderizado

Short description:

React detecta cambios de estado en el árbol de componentes y determina si continuar con el renderizado o comenzar de nuevo. Si ocurre un cambio de estado, React verifica si se llamaron APIs como useState o setStates, que pueden requerir un nuevo dibujo. Para prevenir estados de UI inválidos, React proporciona APIs para que las bibliotecas de gestión de estado le notifiquen las actualizaciones de estado y decidan si volver a renderizar el árbol de componentes completo o parcial.

Si no sucede nada, sigue siendo el mismo proceso, al final, se actualiza el DOM, y la nueva UI es visible, pero si aparece ese clic, ahora podemos ejecutarlo mucho antes. No tenemos que esperar a que se actualice el DOM completo. Ahora, si eso sucede, code aquí puede ejecutarse, y puede hacer lo que quiera hacer. Y en el caso de un manejador de eventos o una solicitud AJAX completada, por ejemplo, eso podría cambiar potencialmente el estado de nuevo, lo que haría que React dijera, oh bueno, aparentemente lo que estábamos renderizando ha sido invalidado por otro cambio de estado. Ni siquiera vamos a molestarnos en continuar con esto porque ya está invalidado. Vamos a volver al principio y empezar a renderizar todo de nuevo. O, este manejador de eventos de clic code podría no cambiar ningún estado para React. Así que React dice, bueno, ejecutamos este pedazo de otro code, todo muy útil pero no interesante para nosotros, y simplemente continuaremos con el ciclo de renderizado actual y mostraremos los resultados de lo que le sucedió al usuario. Así que React detecta, ¿se llamó a alguna de nuestras APIs como use state, set states, cualquiera de estas cosas, que hacen que el árbol de componentes tenga que volver a dibujarse potencialmente. Si no, continuará, pero si lo hicieron, funcionará. Y ahí es donde entra el desgarro del estado. Supongamos que tenemos algunos estados, y déjame coger mi bolígrafo. Tenemos algún objeto de estado y hay un valor aquí. Digamos que tiene el valor uno. Y este componente lo usa, y, ¿por qué no dibuja? Mi bolígrafo no está ayudando. Así que ese componente dibuja. Y este componente usa ese mismo estado. Ahora, supongamos que esto actualiza los estados. Dice, bueno, eso no es uno. Eso es en realidad un dos. Ahora, si React simplemente continuara con su renderizado sin darse cuenta de que el estado ha cambiado, entonces los componentes de la izquierda aquí se renderizarían con uno, y esto se renderizaría con dos para el mismo pedazo de estado, y entraríamos en algún tipo de UI inválido donde el estado estaba medio actualizado y medio no. Así es donde React ofrece nuevas APIs para los desarrolladores de bibliotecas que hacen bibliotecas de state management donde puedes notificar a React, bueno, hicimos algo que causó que el estado se actualizara, evalúa eso, y decide si necesitamos volver a renderizar el árbol de componentes completo o parcial y no continuar o prevenir estos tipos de errores.

Mejorando la capacidad de respuesta con Start Transition

Short description:

Cuando instalamos React 18 y comenzamos a usar create route, comenzamos a usar el renderizado concurrente. Sin embargo, la lista de números primos seguía siendo lenta. Por defecto, las aplicaciones se comportan de la misma manera que antes. Para marcar una diferencia, podemos usar la API de start transition para diferenciar entre trabajos de alta y baja prioridad. Al asignar la parte de número primo como una prioridad más baja que el valor de entrada del rango, podemos mejorar la capacidad de respuesta. Este cambio, logrado mediante el uso de start transition, permite que la lista de números primos se actualice solo cuando el valor se estabiliza, lo que resulta en una aplicación más rápida y receptiva. La diferencia entre start transition y debounce o throttle es que start transition no se basa en el tiempo, sino en el tiempo de CPU disponible. Este simple cambio tiene un impacto significativo en la UI y la capacidad de respuesta de la aplicación.

Ahora, tan pronto como comenzamos a hacer concurrent rendering, en realidad, o lo siento, debería decir, cuando instalamos React 18 y comenzamos a usar create route, en realidad comenzamos a usar este renderizado, pero realmente no nos ayudó con la lista de números primos. Si voy aquí y voy al rango de 10,000 y muevo el deslizador, sigue siendo tan lento como lo era con React 17. La razón es que este mecanismo permite que las cosas se inyecten y detecten las actualizaciones de estado. Pero por defecto, las aplicaciones se comportarán exactamente de la misma manera. No van a comportarse de manera diferente. Solo está habilitando la posibilidad. Y hasta que realmente comencemos a usar las APIs para usar esto, no veremos ninguna diferencia. Y hay una API, o en realidad dos, pero están empaquetadas de manera diferente. Así que en realidad es una bajo el capó, que es start transition, que nos permite empezar a usarlo. Porque básicamente lo que hace React ahora es que diferencia entre el trabajo de alta y baja prioridad. Y por defecto, todo es de alta prioridad. Pero con start transition, podemos decir, bueno, este montón de trabajo es en realidad trabajo de baja prioridad. Y si hay algo más importante, puedes saltarte esto. Simplemente descártalo. No te molestes con ello. Eventualmente no habrá más trabajo importante. Y cualquier trabajo que estés haciendo en esa transición de inicio se hará, pero solo las últimas partes de él, no todo. Por lo tanto, se puede descartar mucho trabajo intermedio. Y si miro esto, si muevo el ratón, vamos a números un poco más bajos. Si muevo el ratón en ese tipo de entrada de rango, vemos que estos números primos se vuelven a dibujar y determina si los números son primos o no. Bueno, eso lleva tiempo. Aquí, está bien. Pero con un rango un poco más grande, está bien. Todo ese estado, que determina el valor del deslizador y la lista de números primos están atados juntos y todos se actualizan con alta prioridad. Pero tal vez puedo saltarme la actualización de la lista de números primos siempre y cuando esté cambiando este deslizador porque mientras lo estoy cambiando la lista real que se está renderizando no es tan importante. Y con start-transition, puedo decir, bueno esta parte, la parte del número primo es en realidad de menor prioridad que el valor de esta entrada de rango. Y resulta que hacer eso es bastante simple. Aquí están los componentes reales que son responsables de esa lista. Y puedes ver que hay un rango primo aquí que establece el número primo máximo para calcular. Y luego hay un bucle aquí para cada número individual. Así que eso es, ¿dónde están los componentes, vamos a cerrar todos estos. Vamos en primos, eso está aquí. Y ahora, siempre que en ese rango primo, por lo que ese elemento superior, ese deslizador, se actualiza, inmediatamente establecerá estos max primes, que es un estado normal, que renderiza este componente, que inmediatamente crea todos esos componentes de verificación de número primo y comienzan a hacer su cosa. Bueno, no podemos hacer eso. Bueno, hagamos eso un poco más lento o de menor prioridad, debería. Start transition. Start transition toma un callback. Así que ponemos ese code allí y ese es todo el cambio. Así que start transition fue importado de React. Parte de React 18. Parte de React 18. Ahora volvemos aquí con los números bajos. Casi el mismo comportamiento. Voy al rango de 10,000, que era lento antes. Hago clic en algún lugar y responde de inmediato. Arrastro, el deslizador responde de inmediato pero la lista de números primos no se actualiza hasta que me detengo y se estabiliza. O si muevo el ratón lentamente, ocasionalmente tendrá tiempo para actualizar. Allí, en realidad se actualizó, pero no realmente. Pero ahora, incluso si voy a los números muy grandes hasta un millón, puedo mover este deslizador y responde agradable y rápido, realmente reactivo. Pero la lista de números primos que en realidad no se vuelve a calcular hasta que el valor se estabiliza. Entonces, realmente estamos usando el modo concurrent ahora. Hemos marcado una diferencia. El valor del deslizador es de alta prioridad. La lista de números primos es de baja prioridad y esa es la parte costosa. Así que ahora se vuelve mucho más receptivo, mucho más rápido. Y eventualmente, todo será consistente. Y si vuelvo a los números un poco más lentos y muevo el ratón lentamente, ocasionalmente verás que se actualiza. Cuanto más grandes se vuelven los números, más costoso se vuelve. Así que se vuelve menos frecuente. Entonces Christina pregunta, ¿qué tan diferente es esto bajo el capó de debouncing las entradas? Y esa es una muy buena pregunta porque con react 17 y antes debounce o throttle serían las opciones a seguir para hacer o para resolver un problema de performance como este. Bueno, la gran diferencia entre debounce y throttle por un lado y start transition por el otro es que debounce y throttle se basan en el tiempo. Podría decir aquí, quiero establecer este valor en debounce después de un segundo de retraso, lo que básicamente significa actualizar este valor máximo primo si esa función no ha sido llamada durante un segundo o si uso throttle, sería un caso de como máximo una vez por segundo, por muy a menudo que se llame, lo que significa que si estoy en los números bajos, que son realmente receptivos, incluso aquí, si muevo el deslizador, tomaría un segundo antes de que los números primos reales se actualicen, porque ese es el throttle. Pero con la transición de inicio, no es una cuestión de tiempo. Es una cuestión de tiempo de CPU disponible. Y aquí hay mucho tiempo disponible. Así que es realmente receptivo. Aquí, no hay tanto tiempo disponible porque el renderizado lleva más tiempo. Así que simplemente va tan pronto como puede. Así que esa es la diferencia allí. Así que un cambio bastante simple, pero tiene un gran impacto en la UI y la capacidad de respuesta de la aplicación.

Introducción a Start Transitions

Short description:

Las transiciones de inicio deben usarse con juicio. En algunos casos, como un deslizador receptivo, tiene sentido utilizarlas. Sin embargo, hay una desventaja en la transición de inicio: no proporciona retroalimentación cuando la lista de números primos se vuelve obsoleta. Exploraremos otra API que aborda este problema.

Normalmente no querrás empezar a introducir transiciones de inicio en todas partes. Tiene que tener sentido. Como en un caso aquí donde tengo el deslizador que necesita ser receptivo, pero esta UI puede quedarse atrás, eso tiene sentido. En otros casos puede que no. Realmente depende de las circunstancias si tiene sentido. Una desventaja de la transición de inicio que estoy usando ahora es que no hay retroalimentación aquí. Como la lista de números primos no se actualiza, pero no puedo ver que actualmente está obsoleta. Estoy usando una lista obsoleta allí. Así que después de esto veremos otra API que bajo el capó también nos da una transición de inicio pero de una manera ligeramente diferente para que podamos solucionar eso.

Uso de la API useTransition en React 18

Short description:

En esta sección, aprendimos cómo usar la API useTransition en React 18 para iniciar transiciones y obtener el estado actual de las transiciones pendientes. Al usar useTransition, podemos mostrar una interfaz de usuario específica cuando estamos en un estado de transición. Realizamos un cambio sencillo en el componente PrimeNumbers para usar useTransition en lugar de startTransition, y pasamos la bandera isPending al componente CheckNumber para mostrar un icono de reloj de arena durante las transiciones. Este cambio mejoró la capacidad de respuesta de la interfaz de usuario, y ahora podemos ver el estado pendiente durante las transiciones. Por favor, realiza este cambio en tu código. Después de eso, discutiremos las razones para tener ambas APIs, startTransition y useTransition. Ten en cuenta que useTransition no está relacionado con suspense y no implica lanzar promesas.

Entonces el resultado, el deslizador receptivo y, bueno, la lista de números primos que se queda un poco atrás. Entonces Alexey preguntó, ¿podemos envolver nuestro array de números primos solamente? Quería actualizar el estado del componente pero renderizar nuestros números dentro de start transition. No estoy seguro porque no renderizas dentro de un start transition. Tenemos todo esto code aquí que se ejecuta con el render. La API de prueba es un poco diferente. La cosa es que aquí, estos valores se llenan en base a ese max prime. Así que básicamente nos aseguramos de que esto no se actualice. Así que la lista realmente no cambia. Sí, solo preguntaba porque, si quieres ver el valor real mientras arrastramos este elemento de UI, si quieres verlo en cada uno, como cada tick, ¿verdad? como cada vez que lo mueves incluso un poco, pero realmente no quieres como volver a renderizar todo. Lo mostraré. Déjame mostrarte cómo funciona el componente prime range. Aquí, puedes ver que este es el input del deslizador. Ahí ves en el cambio, realmente llama a los valores on change, que es el manejador externo que estamos cambiando, que acabamos de cambiar aquí. Y tiene su propio setmax prime range, que es su propio estado interno aquí, que se usa para su propio valor. Así que eso se actualiza inmediatamente. El otro manejador se llama, y eso se ejecuta en una prioridad más baja debido a ese start transition. Y por eso este siempre está actualizado y el deslizador es receptivo. Y ahora este puede quedarse atrás. Podría haber puesto esa transición aquí también, pero porque básicamente aparece dos veces aquí. Así que tendríamos que copiarlo. Pero por supuesto aquí, puedes hacer exactamente lo mismo. Duplica este estado diciendo, tengo bueno, una versión del valor del estado basada en la transición y la versión directa del valor del estado. Excepto en este caso todavía quieres prevenir que esto se vuelva a renderizar. Así que probablemente tendrías que cambiar esto en otro componente puro y hacer toda la lógica allí. Por cierto, otra comprobación que harías... o optimization que normalmente harías es que el número de comprobación sería un componente puro. Aquí, no lo es. Realmente está haciendo su renderizado cada vez. Y realmente en cada renderizado aquí calcula si el valor es primo o no. Así que definitivamente no es una versión optimizada de este componente. Pero si lo optimizo, sería mucho más difícil mostrarte el comportamiento de start transition. Así que start transition es bastante útil para eso. Pero resulta que, hay una segunda API, useTransition, que podemos usar, que hace más o menos lo mismo, pero nos da un poco más. Y lo que hace es, startTransition es solo una función que podemos importar, pero useTransition es un Hook. Y además de permitirnos iniciar transiciones, también nos dará el estado actual. ¿Estamos en una transición pendiente o no? Y eso puede ser útil si quieres renderizar alguna interfaz de usuario específica para BEC UI, tal vez hacerlo claro que estamos en algún tipo de estado de transición. ¿Cómo hacer eso? Realmente muy fácil. Eso es números primos. Así que en lugar de startTransition, voy a importar useTransition. Y voy a llamar a eso, no toma parámetros. Devuelve dos cosas. una bandera isPending y una bandera startTransition. startTransition así. Así que este startTransition funciona exactamente igual que el que usamos antes. Así que no tengo que hacer ningún cambio allí en absoluto. Esta bandera isPending es verdadera o falsa si estamos actualmente en alguna transición. Así que podríamos usar eso. Resulta que este componente de número de comprobación ya tiene algunas capacidades allí. Ya tiene un isPending opcional. Y si lo hace en lugar de hacer el marcador de comprobación cruzar para si es primo o no, va a cortocircuitar eso y simplemente nos mostrará uno de esos iconos de reloj de arena. Así que todo lo que necesito hacer es pasar eso aquí. Y ahora si vuelvo a mi componente PrimeNumbers y lo muevo, ves que obtenemos relojes de arena hasta que realmente se estabiliza. Y si voy a los números grandes, todavía un deslizador receptivo. bueno, casi tan receptivo. Se queda un poco atrás, pero la UI se actualiza. También podría haber hecho algo más como tal vez mostrar estos en gris o algo así. Tal vez no renderizarlos. Tal vez lo que sea apropiado en tu UI. Con un cambio bastante trivial. Básicamente, en lugar de importar start transition, importa use transition y empieza a usar eso. Así que, bastante simple de hacer. Cambio mínimo y nos da algunos beneficios agradables. Llegamos a ver que estamos en un estado pendiente. Ahora, por favor, realiza este cambio. Y después de eso, hablaré brevemente sobre por qué tenemos ambas APIs, porque la primera vez que vi esto, pensamos, si start transition nos da lo que ya nos da use transition, ¿por qué necesitamos ambos? Pero resulta que hay algunas buenas razones para tener ambos. Pero hablaremos de eso después de hacer esto. Así que voy a abrir las salas de breakout de nuevo por cinco minutos, y veo que hay una pregunta. ¿También, una pregunta de Amir, es compatible con suspense? Esta es realmente una API no relacionada. Esto no tiene nada que ver con suspense porque no se lanzan promesas aquí. Así que en ese sentido, es completamente compatible porque no están relacionados.

Uso de StartTransition y UseTransition

Short description:

No necesitas usar suspense. De hecho, no hay componentes de suspense, o en realidad hay en la raíz, pero no se usan específicamente para esto. StartTransition es más rápido, pero no ofrece retroalimentación adicional. Entonces, sí, ambos tienen sus ventajas y desventajas y ambos son útiles. Con Use Transition, puedo mostrar el hecho de que estamos cargando un nuevo usuario aquí dentro de esta lista y tener un poco más de control sobre cómo aparece todo. El clic y la transición aquí están en diferentes límites de suspense ahora, por lo que no cooperan. Pero si entro en detalles del usuario, y eliminamos estos límites de suspense, ahora viven en el mismo límite de suspense. Vemos que se ha atenuado, y ya no vemos ningún spinner, pero estamos dentro de una transición, y controlamos exactamente lo que queremos hacer.

No necesitas usar suspense. De hecho, no hay componentes de suspense, o en realidad hay en la raíz, pero no se usan específicamente para esto.

Vale. Todos han vuelto. Todos tuvieron una agradable retroalimentación visual ahora desde el inicio de la transición. Sí, tengo algo, básicamente se ve más bonito, digamos, tenerlo renderizado después de que, pongas el punto en algún lugar como a la izquierda y a la derecha. Sin embargo, acabo de ver esto, después de un tiempo cuando quieres mover este punto, entonces mueves el punto, luego la tabla con los números se está renderizando o volviendo a renderizar y no puedes mover el punto o el punto se mueve realmente muy, muy lento. No es muy suave. Sí, como. Cuando tienes un gran data. Refrescar y luego ir a 100,000. Por ejemplo. Entonces al principio. Sí. Entonces ahora es como, sí, pero cuando sueltas el punto ahora, sí y se renderizará. Y ahora cuando intentas moverlo, sí, como ves, se queda atascado en algunos puntos. Parece que cuando React tiene esta oportunidad de renderizar, finalmente renderizar esta lista, toma todos los recursos y no libera esos recursos al navegador mientras está renderizando esta enorme lista. Todavía considera toda esta lista como un solo bloque, como una sola pieza de trabajo, unidad de trabajo. Sí. Se mantiene receptivo para mí, pero no es tan receptivo como antes con StarTransition por sí mismo. No se queda atascado para mí. Dicho esto, si arrastro ahora, el primer rerenderizado en realidad lleva más tiempo. Sí, parece que, porque estamos definiendo el hook en el renderizado, ¿significa que hace el primer renderizado y luego desencadena el StarTransition? Sí, eso es correcto. Y en realidad eso es un muy buen punto para llevarme a la siguiente diapositiva, porque mencioné que iba a hablar sobre por qué tenemos tanto StarTransition como UseTransition. Bueno, como mencionaste, UseTransition es un hook. Y eso significa que solo puede ser usado desde un hook o un componente funcional, pero tiene que empezar con un componente funcional en algún lugar. No puede empezar desde alguna biblioteca o algo así. Y StarTransition es solo una función que podría empezar desde cualquier lugar. Podría empezar desde un componente basado en clases, desde un componente funcional, desde alguna otra biblioteca que conozca sobre React. Entonces StartTransition es más flexible. La otra cosa, StartTransition inicia la transición y luego se termina. UseTransition, llamas al StartTransition que se devuelve desde UseTransition, también inicia la transición, pero luego tiene que desencadenar un ciclo de renderizado adicional con esa bandera isPending establecida en verdadero. Entonces obtienes un renderizado adicional. Y en este caso, tengo un conjunto bastante grande de números primos aquí. Creo que estoy renderizando 10,000 de ellos. Entonces, la primera vez que lo moví, primero tiene que renderizar esos mismos 10,000 componentes para que, de nuevo, todos con la bandera isPending sea verdadera. Y solo entonces puede dejar de renderizar esos y estamos en la transición. Así que es ese primer re-renderizado el que en realidad hace que parezca más lento o no solo parece más lento, es más lento. Entonces el hook useTransition es un poco más lento debido al renderizado adicional, pero nos da retroalimentación adicional y necesita ser usado desde un componente. StartTransition es más rápido, pero no ofrece retroalimentación adicional. Entonces, sí, ambos tienen sus ventajas y desventajas y ambos son útiles. Ahora, resulta que con las transacciones, puedes hacer más específicamente UI transacciones porque en este caso, en realidad necesitamos la retroalimentación porque en esta lista de usuarios, si hago clic en el usuario, veo Spinners de carga, pero tal vez en realidad querría mostrar el hecho de que estamos cargando un nuevo usuario aquí dentro de esta lista y tener un poco más de control sobre cómo aparece todo, tal vez no mostrar spinners aquí, pero simplemente atenuar esto o algo así. Bueno, resulta que, con Use Transition, puedo hacer exactamente eso. Así que vamos a hacer eso. Así que cerraremos esto. Volveré a mi lista de usuarios y dentro de este clic donde dije seleccionar al usuario, en realidad puedo empezar a hacer eso dentro de una transacción. Así que podemos empezar a importar use transition, igual que antes. En realidad, eso es solo, lo cerré. Solo copia esa línea, toma esa transición de inicio aquí. Entonces de nuevo, eso debería ser una flecha como esta y una llave más. Y tenemos una transición de inicio allí. Y ahora podría hacer algo con esa bandera isPending y tal vez pasarla aquí. Así que podría mostrarlo un poco diferente. Y no está en la interfaz todavía. Así que vamos a añadirlo allí. Hay un Booleano. Lo recuperamos de las props. Y luego podría hacerlo un poco transparente con un estilo dinámico. Así que opacidad. Si estamos pendientes lo estableceremos en 0.2 o algo así, y de lo contrario lo dejaremos en el valor predeterminado. Al establecerlo en indefinido básicamente no lo estamos estableciendo. Ahora, en teoría, eso debería funcionar. En la práctica, todavía no del todo. Permíteme mostrarte lo que sucede primero. Nada nuevo. ¿Por qué es eso? Bueno, porque los detalles del usuario y las películas favoritas tienen sus propios límites de suspense, por lo que el clic y la transición aquí están en diferentes límites de suspense ahora, por lo que no cooperan. Pero si entro en detalles del usuario, y vamos a deshacernos de estos límites de suspense, límite de suspense allí, ahora viven en el mismo límite de suspense y obtendrán un poco más. Así que hago clic en el usuario. Vemos que se ha atenuado, y ya no vemos ningún spinner más, pero estamos dentro de una transición, y controlamos exactamente lo que queremos hacer. Ahora, eso ya estaba cargado.

Mejorando la Experiencia del Usuario con useTransition

Short description:

Para mejorar la experiencia del usuario, podemos actualizar el estilo activo del usuario inmediatamente al hacer clic, en lugar de esperar a que se complete la transición. Esto se puede lograr duplicando el estado y utilizando el hook useTransition. Al usar useTransition, podemos tener un control total sobre cómo se actualizan los detalles del usuario y evitar que aparezcan spinners. Incluso podemos renderizar indicadores adicionales, como un reloj de arena, condicionalmente para mostrar que el usuario se está cargando. Es importante duplicar el estado y establecer el estado dentro de la transacción para los datos que no nos importan de inmediato, y establecer el estado fuera de la transacción para los datos que sí nos importan de inmediato. Este cambio puede mejorar significativamente la capacidad de respuesta de la aplicación. Por favor, hagan este cambio y nos vemos aquí en cinco minutos.

Permíteme hacer esto de nuevo. Lo único es que, si hago clic en el usuario, como hago clic en Spares ahora, el bucle permanece resaltado hasta que se completa esa transición. Así que queremos el estilo activo no después de que todo esto se haya cargado, queremos actualizar eso un poco antes. Así que en realidad tenemos que hacer un poco más de trabajo aquí porque ese estilo activo aquí se hace aquí basado en el usuario seleccionado que estamos estableciendo pero en una prioridad más baja. Así que esto realmente vuelve a renderizar con ese usuario seleccionado hasta que esa transición ha terminado. Así que lo que queremos hacer en su lugar es decir bien, necesitamos duplicar ese estado. Necesitamos el usuario seleccionado o el ID del usuario. Así que vamos a copiar esto. Necesitamos el ID del usuario seleccionado y establecer el ID del usuario seleccionado. El ID del usuario es un número, así que podemos establecerlo por defecto a NAN, no es un número. Y luego aquí, podemos comparar el user dot ID con el ID del usuario seleccionado. Y luego fuera de la transacción, establecemos el ID. Y eso es el user dot ID. Y ese retorno en realidad no es necesario. No devuelve nada, de todos modos. Así que ahora el usuario se resalta tan pronto como hago clic en él. Y los detalles se actualizan dentro de la transacción. Y tengo el control exacto de cómo se actualizan. Pero noten cómo no aparece ningún spinner ahora. Los límites de suspense con sus fallbacks en realidad no inician ninguna de las renderizaciones de fallback. Porque estoy usando el hook useTransition, básicamente me dejan decidir cómo quiero alimentar al usuario. Puedo moverlo también. Puedo dejarlo. Puedo quitarlo. Realmente no importa. No hace nada porque no hay límites de suspense dentro de él. Y básicamente depende completamente de mí. Pero esa es otra buena capacidad que tengo, que no tenía antes. Así que en lugar de usar la lista de suspense, puedo ir aquí y puedo mover la solicitud. Y puedes ver, como puedes ver, eso es lo que hice. Mi lista, para coordinar cómo funcionan diferentes componentes de suspense, ya sea uno o más, no importa. Todos se enlistan en esta transacción porque todos son parte del mismo límite de suspense. Pero recuerden, tienen que ser parte del mismo límite de suspense. Si pongo uno de vuelta, digamos para la película, entonces va a tener su propio comportamiento. Ahora, en realidad esperaba ver un spinner aquí. Pero por alguna razón, no estoy viendo el spinner. Interesante. ¿Es eso debido a la lista de suspense? Lo dudo, pero vamos a comprobar. No, así que supongo que el useTransition anula todo el suspense y la lista de suspense. Siempre y cuando sea parte de él. Si también habilito este suspense, no es parte de él. Ahora sí obtenemos los spinners. Quitamos todos esos de nuevo. Así que, lo cual en realidad creo que es un comportamiento bastante ordenado. Ahora tienes el control total y puedes incluso hacer algún otro renderizado. Tal vez aquí quieras renderizar el hecho de que este usuario se está cargando con otro indicador, algo como... Inserta ese reloj de arena allí y solo hazlo condicionalmente. Si está pendiente, entonces queremos el reloj de arena. Si no, no queremos nada. Así que ahora, si hago clic renderizando todo, eso no era exactamente mi intención, así que vamos a añadir esta comprobación. Así que ahora estoy renderizando ese reloj de arena solo para el usuario que estoy cargando actualmente. Lo que quieras. Libertad completa porque obtienes control completo ahora debido a esa bandera isPending, que realmente me gusta. Así que. Ese mismo cambio que acabo de hacer, pero recuerda, tienes que duplicar el estado, establecer el estado dentro de la transacción para las cosas que no te importan de inmediato y establecer dentro de la transacción y establecer el estado fuera de la transacción para las cosas que te importan de inmediato. Y recuerda, te vuelves a renderizar y así. Si las cosas son lentas debido a los tiempos de renderizado, entonces todavía no obtendrás todos los beneficios. Así que el componente UserDetails sin el suspense y la lista de suspense. Y el resultado. Así que por favor, vayan y hagan esto. Abriré las salas de breakout y después de eso hemos terminado. Este es el último ejercicio que vamos a hacer. Así que solo para concluir y hemos terminado con esta masterclass. Pero por favor, vayan y hagan este cambio y nos vemos aquí en cinco minutos. Y todos han vuelto. Así que había una pregunta que me perdí antes de Alexi. ¿Cómo sabe StartTransition si los datos están listos y las promesas están listas para ser resueltas? En realidad no he mirado en el código fuente de React, cómo funciona exactamente esto. Pero mi suposición es que busca el límite de suspense más cercano en el padre y verifica su estado. ¿Está suspendido? Entonces sabe que la bandera de expansión debería ser verdadera. Y cuando eso se resuelve, reiniciará esa bandera y los componentes se renderizan de nuevo.

Interacción entre Suspense y Start Transition

Short description:

Suspense y start transition trabajan juntos para manejar la interfaz de usuario de fallback y comunicarse entre sí. El código fuente de React es complejo y desarrollado por individuos talentosos.

Y por supuesto, esa última parte ya es automática gracias a suspense. Es solo que suspense sabe sobre start transition también, o al menos el hook use transition porque no muestra su interfaz de usuario de fallback. Así que no estoy seguro de cómo se comunican, pero de alguna manera hay comunicación entre los dos en eso. Suspense debería hacer un poco menos y start transition debería hacer un poco más. Bueno, magia. No estoy seguro de la magia, pero digámoslo de esta manera. Si te sumerges en el código fuente de React, es complejo. No es un trozo trivial de código, ni mucho menos. Hay algunas personas muy inteligentes trabajando en eso. De todos modos, eso es el final de la masterclass. Así que conclusión suspense, utilizable hoy con React 17. Las cosas funcionan. Puedes empezar a buscar datos o a buscar componentes de forma perezosa usando suspense. Eso funciona perfectamente. Usa límites de error, anida límites de error, anida o paraleliza suspense según lo necesites. Tener diferentes límites de suspense que cooperen no funciona. No puedes hacer eso en React 17 todavía, pero con React 18 puedes. Usa suspense list para eso. Usa el hook use transition para eso. Usa el start transition ya sea directamente o usando el hook use transition para diferir el trabajo de baja prioridad y hacer aplicaciones grandes y complejas más responsivas. Ni siquiera hemos hablado de la renderización del lado del servidor y todas las cosas que añadieron allí. Eso también es mucho más capaz. Así que esperando que React 18 se envíe. Ahora, por supuesto, la pregunta de $10,000 es ¿cuándo se enviará React 18? Y me temo que no puedo responder a eso. No lo sé, tal vez el equipo de React lo sabe pero sospecho que incluso ellos no lo saben. Como de costumbre, probablemente dirán que lo enviarán cuando esté listo. Que probablemente es la mejor respuesta. No lo envíen en un horario fijo, envíenlo cuando esté más bien listo. Ahora, ¿cuándo espero que se envíe? Espero que sea antes de fin de año, pero dado que todavía no tenemos una beta o incluso un candidato a lanzamiento. Todavía estamos en lo que oficialmente es una alfa, esperaría que tome al menos otro mes. Así que dado que es finales de octubre, no espero ver React 18 antes de diciembre. Así que espero que en algún momento de diciembre se envíe. Pero es bastante posible que sea en enero o incluso en febrero. Se sabe que el equipo de React se toma su tiempo para asegurarse de que las cosas estén bien antes de enviarlo, lo cual no puedo culpar. Demasiado software se envía en un horario de tiempo en lugar de un horario de calidad. Así que con eso me gustaría agradecerles por asistir. Espero que haya sido útil. Ya he visto algunos comentarios agradables en el chat, lo cual aprecio mucho. Terminé todo. ¿No hay preguntas? Bueno, gracias por asistir. Espero que sea útil, y disfruta de React 18 cuando se envíe, o antes, jugando con él como esto.

Watch more workshops on topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
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 Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
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, TypeScript, and TDD
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
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.
Web3 Workshop - Building Your First Dapp
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
Nader Dabit
Nader Dabit
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.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
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
Best Practices and Advanced TypeScript Tips for React Developers
React Advanced Conference 2022React Advanced Conference 2022
148 min
Best Practices and Advanced TypeScript Tips for React Developers
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
Are you a React developer trying to get the most benefits from TypeScript? Then this is the workshop for you.In this interactive workshop, we will start at the basics and examine the pros and cons of different ways you can declare React components using TypeScript. After that we will move to more advanced concepts where we will go beyond the strict setting of TypeScript. You will learn when to use types like any, unknown and never. We will explore the use of type predicates, guards and exhaustive checking. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.

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

A Guide to React Rendering Behavior
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
Building Better Websites with Remix
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 Compiler - Understanding Idiomatic React (React Forget)
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
Top Content
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. 
Using useEffect Effectively
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.
Routing in React 18 and Beyond
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.
(Easier) Interactive Data Visualization in React
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!