Video Summary and Transcription
En esta charla, Kent C. Dodds presenta los Componentes del Servidor React (RSCs) y demuestra cómo construirlos desde cero. Explica el proceso de integración de los RSCs con la interfaz de usuario, cambiando a RSC y streaming para mejorar el rendimiento, y los beneficios de usar RSCs con componentes asíncronos. Dodds también discute mejoras con streaming y contexto del servidor, soporte al cliente y cargadores, renderización de componentes del servidor y resolución de módulos, manejo de actualizaciones de la interfaz de usuario y renderización, manejo de botones de retroceso y almacenamiento en caché, y concluye con más recursos para profundizar en el tema.
1. Introducción a los Componentes del Servidor React
¡Hola, Cumbre de React! Mi nombre es Kent C. Dodds y estoy emocionado de darles esta charla y ahora entienden los Componentes del Servidor React. Vamos a construir Componentes del Servidor React desde cero. Vamos a construir un marco de trabajo basado en los Componentes del Servidor React, y este es uno de los mecanismos que normalmente uso para ayudar a las personas a entender los bloques de construcción sobre los que están construyendo. Aquí están las reglas, esto es como un speedrun de la Leyenda de Zelda, tienes que tener reglas, así que no vamos a usar un empaquetador. No estamos usando ninguna dependencia. Estoy asumiendo que ya eres optimista acerca de los RSEs, no estoy aquí para convencerte de que los RSEs son impresionantes, estás dispuesto a sumergirte en los detalles más tarde. Ya conoces los conceptos básicos de los RSEs, así que useClient no es un nuevo concepto para ti. Y luego también eres lo suficientemente inteligente como para no intentar hacer esto en producción, esto, como dije, muy subóptimo. Es una aplicación de una sola página, así que vamos a empezar con una aplicación de una sola página 100% completa, ni siquiera generada por el servidor o algo así, sólo un servidor o una aplicación de una sola página en el cliente.
¡Hola, React Summit! Mi nombre es Kent C. Dodds y estoy emocionado de darles esta charla y ahora entienden los React Server Components. ¡Deseadme suerte! Ahora, si estuviéramos en persona, les pediría que se despertaran y se levantaran. Si físicamente pueden, únanse a nosotros para hacer algunas sentadillas. No estamos en persona, así que no voy a hacer que hagan eso. Pero si ha pasado un tiempo desde que han hecho fluir su sangre, deberían hacerlo porque su cerebro necesita flujo sanguíneo. Vamos a saltarnos eso por hoy, sin embargo.
Muy bien. Entonces, en diciembre de 2020, cuando se anunciaron los Componentes del Servidor, recuerdo que pensé, sentí algo gracioso al respecto. Dije, todos están muy emocionados por los React Server Components y supongo que yo también debería estarlo, pero me siento realmente indiferente al respecto. Lo cierto es que, hace unos meses, me habría vuelto loco con esto, pero sinceramente, Remix resuelve los mismos problemas ya, así que luego tuve una serie de razones por las que me sentía de la manera en que me sentía. Todavía un poco optimista, pero como que sentía que los problemas que los Componentes del Servidor estaban destinados a resolver no me aplicaban tanto. Me faltaban un par de cosas que los Componentes del Servidor hacen que Remix no podrá hacer sin los Componentes del Servidor, así que por favor perdónenme mi vacilación, pero eventualmente yo me acerqué a los Componentes del Servidor, y ahora he construido un framework basado en los Componentes del Servidor. El mío no está destinado para la producción o algo así, pero sí, esta es la transformación que he tenido, y si están familiarizados con esta escena, es donde los hobbits regresan después de su viaje por Mordor y todo, y han cambiado, y yo me siento de esa manera también, después de haber profundizado un poco en los Componentes del Servidor, y ahora puedo apreciar el valor que hay allí. Sé que quizás algunos de ustedes se sienten así, no entiendo los React Server Components, y en este punto tengo miedo de preguntar, pero mi trabajo es tratar de explicar los React Server Components de tal manera que sea lo suficientemente simple para que ustedes lo entiendan. Ese es mi objetivo, así que deséenme suerte.
Muy bien, así que vamos a construir los React Server Components desde cero. Vamos a construir un framework basado en los React Server Components, y este es uno de los mecanismos que normalmente uso para ayudar a las personas a entender los bloques de construcción sobre los que están construyendo, así que no espero que ustedes realmente hagan esto, pero espero que al construir un framework sobre los React Server Components tengan una distinción mucho más clara de qué son los React Server Components y qué es una cosa del framework y lo que sea. Así que aquí están las reglas, esto es como un speedrun de la Leyenda de Zelda, tienes que tener reglas, así que no vamos a usar un bundler. El bundler sólo nos distraería de la idea central de qué son los React Server Components. TypeScript también, así que no queremos tener ninguna build tools en absoluto, simplemente vamos libres sin TypeScript, y ni siquiera JSX, así que van a encontrar algo de createElement como h, eso es corto para hyperscript, y sí, así que vamos a estar usando createElement, la API de createElement directamente. Afortunadamente no vamos a pasar mucho tiempo en las cosas de JSX, así que están bien, no vamos a hacer ninguna optimización, hay muchas por hacer, pero esto no va a ser algo óptimo, y tampoco estamos usando ninguna dependencia. No quiero que se distraigan con todas las demás cosas extra. Básicamente no tenemos dependencias excepto las cosas oficiales de React, React Error Boundary, y Hano.js. Un par de cosas que voy a dar por sentado, estoy asumiendo que ya son optimistas acerca de los RSEs, no estoy aquí para convencerlos de que los RSEs son impresionantes, están dispuestos a sumergirse en los detalles más tarde, así que vamos a pasar por alto un par de cosas, y siéntanse libres de sumergirse más tarde para los detalles. Ya conocen los conceptos básicos de los RSEs, así que useClient no es un nuevo concepto para ustedes. Y luego también son lo suficientemente inteligentes como para no intentar hacer esto en producción, esto, como dije, muy subóptimo.
Muy bien, con todo eso establecido, aquí está la aplicación en la que vamos a estar trabajando para nuestro ejemplo. Es una vista de lista de detalles, actualiza la URL y todas esas cosas que esperarías. Es una aplicación de una sola página, así que vamos a empezar con una aplicación de una sola página 100% completa, ni siquiera generada por el servidor o algo así, sólo un servidor o una aplicación de una sola página en el cliente.
2. Construyendo Componentes del Servidor React
El proyecto se ve un poco así, tenemos nuestra base de datos, nuestro servidor y nuestro directorio de UI. Hacemos una solicitud a nuestra API con la ubicación inicial y usamos un hook para obtener los datos que necesitamos. En el lado del servidor, tenemos un servidor de archivos estáticos y un punto final de API para obtener el barco por su ID. Los RSC implican llamar a una API para obtener la UI renderizada por el servidor. Cambiamos la llamada a la API por RSC y combinamos los datos con la UI en el servidor. Para lograr la componibilidad, hacemos algunas diferencias, importamos react-server-dom-esm-slash-client y lo usamos en nuestro código.
El proyecto se ve un poco así, tenemos nuestra database, tenemos nuestro servidor, este es el servidor Hano.js que tiene un punto final para nosotros, y luego nuestro directorio de UI es todo lo relacionado con la UI. Y luego, aquí hay una pequeña introducción al code con el que vamos a trabajar y modificar con el tiempo. Tenemos nuestra ubicación inicial y nuestra promesa inicial de data, así que estamos haciendo una solicitud a nuestra API con nuestra ubicación inicial que tendrá el ID del barco y cualquier parámetro de búsqueda. Serializamos eso, o deserializamos eso como JSON, y luego estamos usando el hook con esa promesa, y estamos desestructurando los data que necesitamos para nuestra aplicación, y luego esto es nuestro reemplazo para JSX, esta cosa H, createElement como H, pasando estas props a nuestro componente de aplicación. Los detalles específicos no son críticamente importantes para usted en lo que hace este componente de aplicación en este punto. Además, porque estamos haciendo cosas nativas en todos lados, tenemos un mapa de importación en nuestro index HTML, así que cuando decimos importar React y React DOM y React DOM client, estamos extrayendo todos estos de ESMSH, estamos usando la beta de React 19, y sí, esperamos que en un futuro cercano esto sea simplemente React regular. Y finalmente, en el lado del servidor, tenemos un servidor de archivos estáticos para todos nuestros archivos, y luego tenemos un punto final de API para obtener el barco por su ID. También, vamos a tomar los términos de búsqueda, así que estos son básicamente todos los data que necesitas para esta página. Eso incluye nuestro ID de barco, la búsqueda, el barco, y los resultados del barco, que enviamos al cliente en esa carga inicial de la página. Y luego, también tenemos una especie de atrapar todo donde enviaremos ese index HTML. Así que situación típica de SPA sin SSG.
Muy bien. Ahora, hablemos de ello. Vamos de nuestra API a RSC. Así que cuando cargamos la aplicación, estamos haciendo una solicitud para obtener API/barco ID con el término de búsqueda que nos dará todos los data que necesitamos para nuestra aplicación. ID del barco, aquí está nuestra búsqueda, y aquí está el barco y aquí están los resultados para los barcos que coinciden con este término de búsqueda. Esto es bastante típico. Tal vez haces un par de llamadas a la API diferentes, pero en última instancia llamas a una API para obtener tus data. Así que los RSC en realidad no son una cosa enormemente diferente. En lugar de llamar a una API para obtener data, vas a llamar a una API para obtener RSC. Ahora, quiero dejar claro que no tienes que hacer esto a través de una interacción con el servidor en tiempo de ejecución. Puedes hacer esto en tiempo de construcción si quisieras hacer una generación de sitio estático, pero vamos a hacer esto en tiempo de ejecución. Así que nuestro trabajo es cambiar el /API por /RSC, y en lugar de obtener los data aquí y luego combinar los data con la UI en el cliente, en realidad vamos a combinar los data con la UI en el servidor y luego simplemente enviar la UI. Las cosas se ponen un poco interesantes cuando queremos componer las partes interactivas con las partes no interactivas, y por eso no estamos simplemente diciendo, hey, ve a buscarme el HTML e inner HTML todo. Así que vamos a ir un poco más allá de lo que podrías pensar que es la forma más sencilla de hacer esto, pero la razón es porque queremos tener una buena componibilidad con nuestro código del lado del cliente, al que llegaremos más tarde. Así es como logramos esto. Estas son una serie de diferencias que vamos a hacer. Así que primero, para el aspecto del lado del cliente, tenemos nuestro react-server-dom-esm-slash-client. Vamos a necesitar importar esto, por eso lo estamos añadiendo a nuestro mapa de importación, y esto va a ser responsable de algún aspecto de esto. Y luego aquí es donde realmente estamos usando eso.
3. Integrando RSCs con la UI
Ya no importamos la aplicación y cambiamos de una promesa de datos iniciales a una promesa de contenido inicial. En el lado del servidor, utilizamos server DOM ESM/server para serializar nuestra aplicación y los elementos de React en algo que puede ser enviado a través de la red. La llamada a la API ahora es RSC, y en lugar de datos, utilizamos props. Esto nos da pipe, que utilizamos para enviar la respuesta.
Entonces obtenemos nuestro UI slash index, y estamos extrayendo create from fetch de ese módulo. Y esto es un servidor de react o un paquete de react que en realidad no han publicado. Así que notarás aquí que lo estamos extrayendo de mi espacio de nombres en NPM, y la razón es porque esto es muy subóptimo, así que esto es prácticamente solo para demos como la mía. Bueno, una cosa que notarás aquí es que no estamos importando la aplicación. Eso es algo interesante. Así que ya no estamos importando la aplicación y todas las demás cosas que la aplicación está importando. Veremos lo que eso significa aquí en un poco. También estamos cambiando de una promesa de data inicial a una promesa de contenido inicial. Así que hacemos esta solicitud de fetch a slash RSC con esa ubicación inicial, así que eso tiene el ID del barco y la búsqueda. Y luego pasamos esa promesa de fetch a create from fetch. Eso nos da una nueva promesa que luego vamos a pasar a use, y curiosamente, eso nos devuelve algo que es renderizable. Así que en lugar de crear nuestro elemento de aplicación y pasar estas cosas como props y todo eso cosas, podemos simplemente obtener esa aplicación UI de esta llamada RSC, y luego esperamos que esa promesa se resuelva. Obtenemos nuestro final de aplicación aquí, y luego obtenemos nuestro contenido. Se ve impresionante. Entonces, ¿cómo se ve eso en el lado del servidor? Bueno, en el servidor aquí, vamos a estar extrayendo create element de React. Así que esto no es nuevo. Esto es como lo haces con SSR, pero lo que es nuevo es que es renderizado a un stream pipeable proveniente de server DOM ESM slash server. Así que esto va a ser responsable de tomar nuestra aplicación y los elementos de React que creamos con ella y serializarlo en algo que puede ser enviado a través de la red.
4. Cambiando a RSC y Streaming
En lugar de slash API, ahora usamos slash RSC y en lugar de data, usamos props. Este cambio nos permite transmitir contenido RSC en lugar de renderizar JSON. La transmisión es opcional pero tiene sus beneficios.
Entonces, en lugar de slash API, ahora somos slash RSC, y en lugar de data, ahora somos props. Eso es realmente el único cambio allí. Es simplemente más claro que estas son props que vamos a pasar a nuestro componente de aplicación, que estamos renderizando en el servidor. Esto nos va a dar pipe, y luego canalizamos esa respuesta a través de la respuesta saliente aquí. Eso es prácticamente todo. Así que simplemente estás cambiando de renderizar JSON a transmitir este contenido RSC. Y en realidad, técnicamente no necesitas transmitirlo. Hablaremos de por qué la transmisión es agradable en un segundo, pero no tienes que hacerlo si no quieres.
5. Componentes de Servidor de React y Componentes Asíncronos
Cambiamos de enviar JSON a enviar una carga útil de RSC, ya no enviamos código de UI al cliente. En su lugar, solicitamos una versión lista para transmitir de los elementos de React en el servidor. Con los componentes de servidor de React, podemos tener componentes asíncronos y co-localizar datos con la UI que los requiere.
Así que eso es básicamente todo. Ahora tenemos RSCs. Cambiamos de enviar JSON a enviar una carga útil de RSC, y ya no estamos enviando ningún UI code al cliente. No necesitamos hacerlo. Al menos nuestro UI code de aplicación. No necesita ir al cliente, lo cual es genial. Y en su lugar lo que solicitamos, antes estábamos solicitando data, y ahora estamos solicitando esta sofisticada, casi parece JSON pero no del todo, especie de cosas listas para transmitir. Así que esto debería parecer un poco familiar. Esto es como los elementos de React, pero no es exactamente lo mismo, porque no podemos hacer referencia a funciones, así que nuestro componente o nuestros tipos de elementos no pueden ser funciones y ese tipo de cosas. Así que aquí está la forma en que lo pienso. En el servidor, creamos un elemento de aplicación. Y luego lo pasamos a pipeable stream, y eso genera esta versión sofisticada, lista para transmitir, serializada de esos elementos de React. Y eso se alimenta en el create from fetch que está en React server DOM ESM. Create from fetch lo convierte en nuestros elementos de React. Así que tipo div, props, tal y tal, yada yada. Así que ese es el flujo de cómo van las cosas cuando lo pasamos a React server components.
Y ahora que tenemos esto, en realidad podemos hacer un par de cosas geniales. Así que, por un lado, tenemos componentes asíncronos. Así que con eso, podemos ir a nuestro servidor, y sabes cómo estamos agarrando la nave y las naves aquí y metiéndolas en nuestras props y luego enviándolas a la aplicación? Bueno, ahora, ya no necesitamos enviarlas, porque estamos ejecutando en el servidor. Así que los componentes que necesitan esa información pueden ir a buscarla ellos mismos, y todo lo que necesitamos es este contexto global, este ship ID en la búsqueda. Y luego eso puede ser usado para recuperar las naves en la búsqueda de naves y cosas así. Y así, si miramos nuestra aplicación de UI, ya no estamos aceptando esas props. Ya no estamos reenviando esas props. Y luego en los componentes individuales, podemos decir, hey, puedo ser un componente asíncrono ahora, porque estoy en el servidor. Y puedo obtener la nave. Y aquí mismo, puedo buscar la nave. Y eso en realidad reduce drásticamente esto es una de las cosas que me faltaba acerca de React server components era la co-localización de data a la UI que requiere los data. Hemos estado persiguiendo ese sueño durante mucho tiempo.
6. Mejoras con Streaming y Contexto de Servidor
Remix tiene cargadores y acciones a nivel de ruta. El streaming se puede lograr con los componentos de servidor de React envolviendo partes de la UI en límites de suspense. El contexto del servidor elimina la necesidad de pasar props por todas partes.
Y Remix tiene eso con cargadores y acciones. Pero eso es a nivel de ruta, que es suficientemente cercano la mayoría de las veces. Pero poder hacerlo directamente en el componente, eso tiene algunas implicaciones enormes, como distribuirlo en NPM, por ejemplo. Pero no vamos a profundizar demasiado en eso.
Continuemos, porque tengo muchas más cosas que quiero mostrarles. Así que hablemos de streaming. Ahora, lo que tenemos ahora es que cuando accedo a la página, tomará tanto tiempo como sea necesario para obtener todas estas cosas antes de que pueda mostrar algo de ello, lo cual es un dolor. Así que lo genial es que en realidad podemos transmitir estas cosas. Ahora que tenemos los componentes de servidor de React. Y aquí podemos simplemente envolver las diferentes partes de mi UI en límites de suspense. Y una vez que tienes eso en su lugar, ahora tendremos los diferentes límites de suspense que aparecen en su lugar. Y así cualquier cosa que no esté envuelta en un límite de suspense o una vez que esa área de la aplicación resuelve las cosas que está esperando, podemos mostrar eso de inmediato. Y por supuesto, renderizar esto en el servidor sería aún mejor. No tendrías ese estado de carga inicial tampoco, pero estamos manteniendo esto simple. Pero esto es genial porque tienes mucho control sobre eso. Otra cosa rápida, una victoria rápida que podrías haber oído es el contexto del servidor. Y así aquí antes, teníamos estas props, el ship ID y la búsqueda que teníamos que pasar a nuestro componente de aplicación.
7. Mejoras con Soporte al Cliente y Cargador
Ahora, si estás utilizando almacenamiento local asíncrono en Node.js, puedes almacenar datos en el almacenamiento de datos de la nave, eliminando la necesidad de pasar props en todas partes. Hablemos de agregar soporte al cliente. Necesitamos un mecanismo para renderizar componentes del lado del servidor y cargar componentes de la interfaz de usuario del lado del cliente. Utilizamos un cargador para convertir el contenido del módulo y serializarlo como referencias para renderizar componentes específicos.
Ahora, si estás utilizando almacenamiento local asíncrono en Node.js, entonces puedes almacenar todos esos datos dentro de este almacenamiento de datos de naves especiales y luego renderizar tu aplicación. Y luego todos los diferentes componentes pueden recuperar eso del almacenamiento de datos de la nave, algo así como el contexto y obtener esos valores. Por lo tanto, ya no tienes que pasar esas props por todas partes, lo cual creo que es una victoria sin duda.
Bueno, sigamos, porque todavía tenemos mucho más de qué hablar. Hablemos de agregar soporte al cliente. Ahora mismo, si cometo un error de algún tipo, va a explotar en mí. Y probablemente podría manejar esto mejor, incluso yo mismo. Pero quiero manejar esto de manera declarativa con límites de error. Y los límites de error son una pieza de lógica de UI. Así que estamos almacenando el error en nuestro estado de límite de error. Y por lo tanto, necesitamos tener alguna solución que nos permita tener código del lado del cliente. Ahora recuerda, no tenemos ningún componente del lado del cliente aquí excepto lo que está en nuestro índice. Y por lo tanto, necesitamos tener algún mecanismo para decir, Oye, sí, renderiza esto en el servidor, pero necesito que tengas pequeños espacios donde los componentes de UI pueden ser cargados. Y necesito saber cómo cargar esas cosas. Así que lo interesante de eso es que no puedes hacer que tus componentes de servidor rendericen eso por varias razones. Viven en diferentes entornos. Y por eso, lo que terminamos haciendo es, al menos en este ejemplo, usarías un bundler para esto. Pero en nuestro ejemplo, en realidad podemos usar un cargador. Así que tenemos este registro RSC cargador, que está aquí. Registra nuestro cargador RSC. Y nuestro cargador RSC, no voy a profundizar demasiado en esto. Básicamente convierte cualquier, como estamos importando módulos, va a pasar por nuestro cargador aquí. Y si decidimos podemos convertir el contenido de cadena de ese módulo en algo más para que nuestros componentes RSC no rendericen realmente los componentes del cliente y en su lugar lo serialicen para ser una referencia a, Oye, necesitas renderizar este componente en particular. Y así aquí estoy importando este componente de límite de error, que tiene uso del cliente aquí en la parte superior. Esa es la directiva que le dice al cargador, Oye, necesito que me transformes de una manera especial. Así que si miramos cómo se ven los registros de la consola, si registramos en la consola el error de transformación del módulo de límite. Así es como se convierte ese módulo. Dijimos exportar todo desde react error boundary. Y así crea exportaciones para cada una de las exportaciones de react error boundary. Y luego llama a este registro de referencia del cliente desde nuestro react server dom ESM server.
8. Renderizado de Componentes del Servidor y Resolución de Módulos
Cuando un componente del servidor intenta renderizar un componente especial, se encola en react server, Dom ESM. La aplicación del servidor está configurada con una ruta base de módulo para resolver diferentes módulos. El índice de la UI pasa la URL base del módulo para buscar los componentes requeridos para que la UI funcione.
Y de esa manera, cada vez que un componente del servidor intenta renderizar una de estas cosas, es como encolar en react server, Dom ESM para decir, Oye, este es un componente especial. Y te diré qué, incluso puedo decirte dónde encontrarlo, cómo cargar este archivo. Así que cuando necesite ser resuelto, entonces podemos resolverlo. Y aquí, esta es la exportación del límite de error. Aquí está la exportación del contexto del límite de error, yada, yada, yada. Y luego en la aplicación GS donde esto es nuestro componente del servidor, lo que ve es solo esta función. Y así que cuando intenta renderizar eso, en realidad no lo llamas. Recuerda, no estás llamando a tus componentes que estás renderizando react lo está. Pero cuando react ve este componente especial, dice, Oh, no voy a llamar a esa función. En cambio, voy a registrar eso y podemos ver cómo resolvemos ese módulo registrado en algo. Así que aquí tenemos nuestra aplicación, nuestra aplicación del servidor. Y aquí, simplemente le vamos a decir, aquí está la ruta base del módulo. Así que viste esa URL de archivo larga y grande. Esto va a decir, deshazte de todo lo que coincida con esta ruta base del módulo. Así que es como ir al directorio UI y eliminar todo lo que esté antes de eso. De esa manera, podemos saber cómo resolver estos diferentes módulos. Y luego en nuestro índice UI, vamos a pasar la URL base del módulo para que sepa qué URL puede golpear para ir a buscar esos módulos. Y aquí está lo realmente genial es que esto nos permite tener como componentes infinitos. Y luego la carga útil, la carga útil RSE puede decir, aquí están los componentes que necesitas. Y luego el navegador puede ir a buscar solo los componentes que necesita para que esta UI funcione, lo cual, creo, es bastante genial. Y nos permite resolver nuestro problema particular. Este es un componente del cliente justo allí.
9. Manejo de Actualizaciones y Renderizado de la UI
Para manejar las actualizaciones de la UI, hacemos solicitudes de red para obtener actualizaciones para la ubicación actual y obtener el contenido del backend. El componente raíz gestiona el estado para la ubicación actual y el contenido, pasándolo como hijos al contexto del enrutador. La función de navegación actualiza la ubicación y obtiene el contenido, creando elementos de React que pueden ser renderizados en el cliente.
OK, genial. Así que nos queda un poquito de tiempo. Así que probablemente tendrás que profundizar un poco más en un par de estas cosas. Entonces, para las actualizaciones de la UI, lo que tenemos ahora es que cada vez que hago una búsqueda o cada vez que hago clic en uno de estos elementos, voy a obtener una actualización completa de la página. Así que necesitamos manejar eso porque todos los data que están en esta página provienen del servidor. Así que necesitamos hacer una solicitud de red para obtener actualizaciones para obtener los detalles de la nueva nave en la que he hecho clic o los resultados de la búsqueda.
Entonces, la forma en que logramos esto es en nuestra UI. Bueno, en primer lugar, tenemos nuestro enrutador de UI. Esto es solo un par de utilidades. Es algo bastante típico del contexto. Tenemos este manejador de enlaces que manejará los clics en los enlaces y llamará a la función de navegación por nosotros. Pero la verdadera esencia de todo esto está en nuestro index.js. Y lo que está pasando aquí es que todavía estamos básicamente haciendo muchas de las mismas cosas que estábamos haciendo antes. Pero lo interesante es que ahora nuestro componente raíz está gestionando un estado para la ubicación actual y también gestionando el estado para el contenido que está obteniendo del backend para esa ubicación particular. Y eso es lo que acaba pasando como hijos al contexto del enrutador. Así que eso acaba siendo renderizado. Así que realmente no cambia nada todavía. Pero ahora tenemos nuestra función de navegación. Esto va a actualizar nuestra ubicación a donde estamos tratando de llegar. Y luego va a obtener el contenido de nuevo. Así que esto está obteniendo contenido RSC. Y cuando eso ha terminado, podemos actualizar la URL. Y vamos a crear a partir de la búsqueda. Así que toma las cosas serializadas de RSC, las convierte en elementos de React que podemos renderizar en el cliente. Eso es lo que es la promesa del próximo contenido. Y luego, dentro de una transición, actualizamos la promesa del contenido. Porque de nuevo, todo esto se está ejecutando de forma serial. Nada de esto se está ejecutando de forma asíncrona excepto lo que está en el callback de then aquí. Y así que decimos instantáneamente, hey, adelante y comienza esta transición. React hace su magia con las transiciones.
10. Renderizado de React y UI Pendiente
React puede renderizar nuevo contenido instantáneamente sin refrescos completos de página. La UI pendiente se gestiona en la interfaz de usuario de la aplicación utilizando la transición pendiente de detalles del barco. El índice de la UI ahora gestiona la próxima ubicación utilizando use deferred value, permitiendo la comparación de las UIs actuales y pendientes. Las condiciones de carrera se manejan estableciendo el último símbolo de navegación al navegar e ignorando las navegaciones no más recientes en el manejador then.
Y luego, una vez que esta promesa se resuelve aquí, entonces React es como, genial, aquí está tu nuevo contenido, y podemos renderizar ese nuevo contenido. Así que básicamente solo llama al servidor de nuevo, ve a buscar el nuevo contenido. Es bastante genial. Y así obtenemos algunas actualizaciones instantáneas a nuestra UI. No tenemos que hacer refrescos completos de página. Y todo está sucediendo simplemente porque decimos, hey, tráeme un poco más de contenido. Y luego reemplazamos el contenido que se muestra.
Muy bien. Así que hablemos rápidamente de la UI pendiente. Así que mientras estoy haciendo clic, notarás que no estamos obteniendo ninguna indicación de que las cosas están sucediendo. Y la forma en que hacemos esto es en nuestra aplicación UI, ahora tenemos esta transición pendiente de detalles del barco. Esto es porque esto es un cliente de uso. Así que tenemos que separar esto porque la gestión de este estado pendiente va a suceder como parte de la gestión de estados reales. Por eso necesita estar en el cliente.
Y luego, si miramos nuestro índice de UI, aquí es donde ocurre la esencia del enrutador y estos cambios. En lugar de gestionar la ubicación, ahora vamos a gestionar simplemente la próxima ubicación. Y nuestra ubicación se derivará de la próxima ubicación utilizando use deferred value. De esa manera tenemos dos UIs. Tenemos la UI que teníamos antes y la UI que vamos a tener a continuación una vez que todo se resuelva. Y de esa manera podemos comparar esos dos y determinar si estamos actualmente pendientes. Y con la próxima ubicación, podemos saber, oh, ¿a dónde vamos? Vale. Sé qué cosa está pendiente. Así que podemos determinar si la búsqueda está pendiente o si el usuario o los barcos son la cosa que está pendiente. Y con eso ahora, tenemos nuestra agradable UI pendiente conectada a nuestro enrutador, lo cual creo que es bastante interesante. Pero hay algunas condiciones de carrera. Simplemente no pude evitarlo. Tenía que mostrarte esto manejando las condiciones de carrera. Solo tenemos la última navegación. Establecemos eso a un símbolo cuando empezamos a navegar. Y en nuestro manejador then aquí, si no estamos en la última navegación, simplemente no hacemos nada. Y eso resuelve los problemas de condiciones de carrera.
11. Manejo del Botón Atrás y Caché
Al presionar el botón atrás, la URL se actualiza pero no llama a la función de navegación. El manejo de esto implica establecer la ubicación, buscar el contenido e implementar la caché utilizando la tienda externa sincronizada. Las entradas en el historial se asocian con las claves en la caché, permitiendo la fácil recuperación de las promesas de contenido. Navegar hacia adelante o hacia atrás genera nuevas claves y las asocia con las correspondientes promesas de contenido.
Tienes que pensar en esas cosas, gente. Vale, genial. ¿Y qué pasa si presionamos el botón atrás? Así que voy a buscar el barco Medix, y luego hago clic en el barco Medix. Y luego, si presiono el botón atrás, no pasa nada excepto que la URL se actualiza porque el navegador se encargará de eso. Pero necesitamos escuchar esos eventos. Porque eso no está llamando a nuestra función de navegación. Así que todo lo que necesitamos hacer para eso es que nuestro use effect aquí va a tener este manejo del estado pop para manejar el estado pop. Y vamos a establecer la ubicación, buscar el contenido para esa ubicación, y todo está bien, excepto que todo no está bien.
Porque estamos haciendo una nueva promesa para buscar algunos data. Así que va a terminar mostrando nuestro límite de suspense. Hay algunas razones interesantes por las que eso sucede, incluso aunque lo estamos haciendo dentro de una transición. Pero es importante que manejemos este caso. Y esto nos lleva a la caché. Así que tenemos que cachear nuestras cosas. Así que tengo esta caché de contenido. Esto está usando la tienda externa sincronizada. Aquí está nuestra tienda. Es un mapa observable que emite un cambio cada vez que cambias algo en la caché. Y luego podemos consumir eso y desencadenar re-renderizados cuando nuestra caché se actualiza.
Pero en última instancia, lo que necesitamos hacer es que necesitamos asociar las diferentes entradas en nuestro historial con una clave y asociar esa clave con una entrada particular en nuestra caché. Así que tenemos nuestra caché de contenido. Ya no estamos rastreando la promesa. En cambio, estamos rastreando la clave en el historial en la que estamos actualmente. Obtenemos nuestra promesa de contenido de la caché en esa clave de contenido. Y luego, cada vez que estamos cambiando el historial, estamos yendo hacia adelante o hacia atrás, vamos a obtener la clave de ese estado en el historial. Vamos a generar una nueva clave si no existe una. Y luego, en base a eso, vamos a usar la promesa que está almacenada en nuestra caché para esa clave en particular. Así que cada vez que hacemos una navegación, vamos a generar una nueva clave y esa clave a esa entrada en nuestro historial y asociar esa clave con la promesa de contenido. De esa manera, mientras estás navegando y yendo hacia adelante y hacia atrás en el historial, ya tenemos eso en memoria así que podemos simplemente renderizar eso. Ahora, la caché es un tema muy amplio.
12. Comentarios Finales y Recursos Adicionales
Una caché simple como esta puede ser relativamente sencilla. Si quieres profundizar más, consulta la masterclass Epic Web y la versión 2.0 de Epic React en GitHub para obtener más detalles.
Es complicado y demás. Pero una caché simple como esta, esperemos que sea relativamente sencilla. Algo en lo que puedes profundizar si te interesa.
Muy bien. Acciones. Oh hombre. Nos estamos quedando sin tiempo. Oh bueno. No, no tenemos tiempo para hablar de acciones. Creo que ya me he pasado de tiempo de todos modos.
Si quieres profundizar más, todo esto proviene de la masterclass Epic Web. Esta es la versión 2.0 de Epic React que pronto estará en Epic Web. Así que puedes revisarlo por tu cuenta. Es de código abierto en GitHub. Y profundiza en algunas de estas cosas si quieres obtener algunos de los detalles. Y hay un montón de otra información allí. Así que siéntete libre de sumergirte. Y ahora entiendes los componentes de servidor de React. Felicidades. Muchas gracias por darme algo de tu tiempo.
Comments