¡Construyamos React Query en 150 líneas de código!

Rate this content
Bookmark

Desde la Cumbre de React del año pasado, React Query ya se ha convertido en una de las bibliotecas de búsqueda de datos más populares y poderosas para React. Para celebrarlo, iremos detrás de escena para ver cómo funciona realmente React Query e incluso construiremos nuestro propio gancho useQuery en solo 150 líneas de código.

30 min
14 May, 2021

Video Summary and Transcription

React Query es una popular biblioteca de sincronización de datos utilizada por desarrolladores independientes, startups y Fortune 500, con más de 1,200 commits y 250 contribuyentes. La charla cubre la creación de una versión simplificada de React Query llamada React Query Lite. Explora conceptos como el almacenamiento en caché, la búsqueda en segundo plano y la recolección de basura. El orador también discute el uso de observadores de consultas y la integración de React Query con React. La charla concluye con una discusión sobre las herramientas de React Native, las pruebas y la estabilidad de la API de React Query.

Available in English

1. Introducción a React Query

Short description:

Hola a todos. Soy Tannyor Lindsly, cofundador e ingeniero de UI UX en Nozzle. Creé la pila TAN, un software de código abierto para React y JavaScript. React Query, la biblioteca que construí, ha ganado una popularidad significativa y es ampliamente adoptada. Ha recibido más de 1,200 commits de 250 contribuyentes y es utilizada por desarrolladores independientes, startups y Fortune 500s. React Query Essentials, mi curso oficial, proporciona material de aprendizaje completo. React Query también aparece en artículos externos, tutoriales y frameworks como Blitz.js.

Hola a todos. Mi nombre es Tannyor Lindsly, y soy cofundador e ingeniero de UI UX en Nozzle, y soy el creador de la pila TAN, donde estamos haciendo todo lo posible para construir software de código abierto para React y JavaScript.

Hace casi exactamente un año, di una charla aquí en la Cumbre de React, donde desglosé las diferencias entre el estado del servidor y el estado del cliente y los desafíos que surgen al intentar gestionar el estado del servidor por tu cuenta. En esa misma charla, presenté una herramienta llamada React Query. Es una biblioteca que construí con la esperanza de aliviar la mayoría de los desafíos de la obtención de data que experimentamos en nuestras aplicaciones de React.

Y desde aquel día hace un año, React Query ha recibido más de 1,200 commits de más de 250 contribuyentes. Y ha sido adoptada por desarrolladores independientes, startups, Fortune 500s y un puñado de equipos de empresas que probablemente no estoy legalmente autorizado a mencionar. También lancé React Query Essentials que es mi curso oficial para aprender la biblioteca de arriba a abajo. Y React Query ha recibido una tonelada de cobertura de artículos externos y tutoriales y material de formación de primera clase como Epic React. Incluso se está utilizando como una característica central para los frameworks emergentes como Blitz.js. Todo este increíble crecimiento y atención ha ayudado a React Query a convertirse en una de las mejores bibliotecas de obtención de data para React y estoy muy agradecido por todo su uso y apoyo que ha recibido hasta ahora. Así que muchas gracias.

2. Construyendo una versión mini de React Query

Short description:

React Query es una biblioteca de sincronización de datos que coordina la obtención, almacenamiento en caché y actualización de datos en su aplicación. Proporciona datos almacenados en caché mientras los actualiza en segundo plano con la frecuencia que tenga sentido. Puede configurar React Query para hacer otras cosas interesantes como sondeo de intervalos, precarga, SSR, paginación, y tiene DevTools dedicados. Hoy, construiremos nuestra propia versión de React Query llamada React Query Lite, que tendrá autofetching, autocaching y recolección de basura. El objetivo es hacerlo en menos de 150 líneas de código.

Hasta ahora, algunos de ustedes probablemente se están preguntando, ¿qué es React Query? Así que para aquellos de ustedes que no están familiarizados con los conceptos generales de la biblioteca, van a querer volver y escuchar algunas de mis charlas anteriores y leer la documentación para familiarizarse. Pero sólo para que todos estemos en la misma página hoy, les daré un rápido resumen de dos minutos de qué es React Query y qué puede hacer.

En pocas palabras, React Query es una biblioteca de sincronización de datos. Coordina la obtención, almacenamiento en caché y actualización de datos en su aplicación. Los datos que maneja pueden provenir de casi cualquier lugar siempre y cuando devuelva una promesa. Se basa en el concepto de obsoleto mientras se revalida, lo que significa que proporciona datos almacenados en caché tan a menudo como sea posible mientras actualiza esos datos en segundo plano tan a menudo como tenga sentido para los componentes que lo consumen. Así que usted proporciona la lógica de obtención y se encarga de todo lo demás automáticamente. Puede colocar las consultas de React Query en cualquier lugar de su aplicación de React a cualquier profundidad, y nunca tiene que preocuparse por hacer solicitudes de red duplicadas o gestionar el estado global o usar el contexto.

Puede configurar React Query para hacer otras cosas interesantes como sondeo de intervalos, precarga, SSR, paginación, hay muchas cosas interesantes que React Query puede hacer. Una de mis favoritas es que tiene DevTools dedicados. Hay mucho que podría decir sobre React Query ahora mismo. Podríamos pasar horas hablando de las cosas interesantes que puede hacer y eso es realmente lo que hago en mi curso de Essentials de React Query. Así que en lugar de hacer eso de nuevo y dar otra charla sobre cómo usar React Query, pensé que sería divertido hoy hacer algo diferente y mostrarles cómo podríamos construir nuestra propia versión de React Query, o al menos una versión miniatura. La llamaremos React Query Lite. Y al hacerlo, esperamos poder obtener una mejor comprensión de cómo funciona conceptualmente bajo el capó.

Para hacer esto, vamos a construir un Cliente de Consulta, un Proveedor de Cliente de Consulta, y un hook Use Query. Y ese hook Use Query va a tener autofetching, autocaching, recolección de basura, y también podremos configurar el tiempo obsoleto y el tiempo de caché. Y la gran esperanza aquí... Estoy esperando... que podamos hacerlo en menos de 150 líneas de código. Así que haremos nuestro mejor esfuerzo. Veremos qué pasa. Hay una advertencia aquí. Quiero decirles que el código que estamos a punto de escribir está muy poco probado. No es seguro en cuanto a tipos. Definitivamente es ingenuo y está lleno de casos límite. No deberías usar esto en producción. Ni en desarrollo, para el caso. Así que, sólo para fines de aprendizaje. Va a ser muy divertido.

3. Resumen de la Aplicación

Short description:

Vamos a sumergirnos en la aplicación que he construido. Obtiene una lista de publicaciones y las muestra individualmente. React Query se encarga de la caché y la obtención en segundo plano. Ahora, vamos a explorar la aplicación.

Así que vamos a ello. a una aplicación que he construido. Y si has utilizado alguno de los ejemplos de React Query, esto debería parecerte bastante familiar. Es una aplicación que obtiene una lista de publicaciones. En este caso, cinco. Podemos hacer clic en ellas y cargará una publicación individual con un título y el cuerpo de la publicación. Podemos pulsar el botón de retroceso. Y puedes ver que React Query ya está haciendo su trabajo aquí. Estamos utilizando el React Query normal, donde si hemos cargado una publicación o una lista de publicaciones, entonces simplemente carga automáticamente la versión en caché. Y luego obtiene en segundo plano, si lo pulsas de nuevo, puedes ver ese pequeño fondo verde obteniendo. Así que esto es genial. Y React Query está haciendo su trabajo. Vamos a repasar la aplicación realmente rápido y te mostraré lo que está sucediendo.

4. Componentes de la Aplicación y Hooks Personalizados

Short description:

Tenemos un cliente de consulta, componente de aplicación, y hooks personalizados utilizando UseQuery. El hook UsePosts obtiene publicaciones, y el componente Posts las muestra. La vista de Post individual muestra publicaciones individuales. También tenemos una función de sleep para simular retrasos de la API.

Aquí tenemos un cliente de consulta que estamos creando. Tenemos el componente de aplicación aquí que es básicamente solo un router donde podemos establecer un ID de post y ver ya sea la lista de publicaciones o una vista detallada de una publicación. Tenemos nuestras React Query DevTools aquí y todo está envuelto en nuestro proveedor de cliente.

Ahora tenemos nuestros hooks personalizados que están utilizando UseQuery. Así que aquí está nuestro hook UsePosts que está llamando a UseQuery con la postKey y la función de consulta para obtener algunas publicaciones. También tenemos StaleTime y CacheTime que usaremos más tarde.

Aquí está el post individual, el hook UsePosts, que toma un ID de post, configura la clave de consulta y la función de consulta para obtener el post individual. Y aquí están nuestros componentes de visualización, el componente Posts donde estamos cargando todas las publicaciones, pasando por nuestros estados de carga y error, y finalmente mostrando nuestra lista de publicaciones. Y también tenemos nuestro indicador de búsqueda en segundo plano justo aquí. Hasta nuestra vista de Post individual, tenemos el ID del post que estamos pasando al hook UsePosts , nuestra consulta de post individual, y estamos haciendo exactamente lo mismo, solo un estado de carga y error aquí, y finalmente mostrando el post individual junto con otro indicador de actualización en segundo plano. Y aquí hay una pequeña función de sleep para que podamos hacer que la API que es realmente rápida parezca un poco lenta, para que podamos ver esos indicadores de carga.

5. Reemplazando React Query con ReactQueryLite

Short description:

Nuestro primer paso es reemplazar la actual React Query con un nuevo archivo llamado ReactQueryLite. Necesitamos satisfacer al proveedor del cliente de consulta que nos está dando un error creando un contexto. Para manejar el error en el hook de uso de consulta, podemos crear una respuesta ficticia que indica que todo está cargando. Esto nos lleva a un estado de funcionamiento donde estamos renderizando algo.

Entonces, nuestro primer paso será eliminar la actual consulta de React y reemplazarla con un nuevo archivo, un archivo en blanco llamado ReactQueryLite. Y obviamente, todo se va a romper, así que vamos a entrar en nuestro archivo ReactQueryLite y ver qué está pasando.

Tenemos un proveedor de cliente de consulta, el cliente de consulta, use query, y las DevTools. Justo de entrada, probablemente no llegaremos a DevTools, así que simplemente devolvamos null en eso y satisfacemos ese requisito.

Lo siguiente que vamos a hacer es que vamos a necesitar satisfacer a este proveedor de cliente de consulta que nos está dando un error. Así que voy a tomar nuestro pequeño proveedor de cliente de consulta code y lo pegaré aquí, y lo que está pasando aquí es que tenemos los hijos que estamos pasando. Toma al cliente, y luego está pasando ese cliente a todos los hijos. Vamos a necesitar un contexto para hacer esto funcionar, así que vamos a crear un contexto muy rápido. Tenemos que crear un contexto, y ahora estamos obteniendo un error porque estamos tratando de leer la propiedad status de indefinido en el hook de uso de consulta. Así que simplemente vamos a juntar una especie de respuesta ficticia de este hook de uso de consulta que dice que todo está cargando todo el tiempo. No data, error indefinido, is fetching true. Así que eso nos lleva al menos a un estado de funcionamiento donde estamos renderizando algo.

6. Creando el Objeto de Consulta

Short description:

Una consulta es un objeto con estado y una función de búsqueda. Crearemos una función llamada createQuery que toma la clave de consulta y la función de consulta como parámetros. Configura el objeto de consulta con el estado inicial, proporciona una función setState para actualizar el estado, y una función de búsqueda para iniciar la búsqueda. Esto es todo JavaScript puro por ahora, pero lo integraremos con React pronto.

La siguiente pregunta que debemos hacernos es ¿qué es exactamente una consulta? Bueno, una consulta al final del día probablemente solo va a ser un objeto, como un objeto de consulta que tiene algún estado en él con una función de búsqueda. Entonces, ¿por qué no hacemos una nueva función aquí abajo llamada createQuery. Va a compartir parte de la firma de nuestro hook useQuery, por lo que la clave de consulta y la función de consulta se van a pasar aquí. Crearemos el nuevo objeto de consulta y lo configuraremos con un estado inicial. Es ese mismo estado que estamos usando aquí. Y vamos a tener una función setState que nos permite actualizar nuestro estado de consulta y una función de búsqueda que nos permite iniciar la búsqueda de eso. Esto es todo solo JavaScript por ahora. Llegaremos a conectarlo con React aquí en un minuto.

7. Actualizador de Estado y Función de Búsqueda

Short description:

Después de configurar el actualizador de estado, creamos una función de búsqueda asíncrona. Establece el estado isFetching en verdadero y borra cualquier error. En un bloque try-catch, llamamos a la función de consulta y manejamos los casos de éxito y error. Finalmente, establecemos queryPromise en nulo y isFetching en falso. Para evitar solicitudes duplicadas, utilizamos la propiedad query.promise y envolvemos la función de búsqueda en lógica que verifica la existencia de una promesa. Creamos un método de suscripción para soportar múltiples instancias de useQuery y notificar a los suscriptores cuando el estado cambia.

Entonces, después de haber hecho eso, necesitamos trabajar un poco con nuestro actualizador de estado. Así que setState va a tomar una función de actualización y básicamente solo ejecutará esa función de actualización con el estado existente y devolverá el nuevo estado, algo así como un reductor. O si has usado setState antes con React, es muy parecido a eso.

A continuación, tenemos nuestra función de búsqueda, y nuestra función de búsqueda va a ser asíncrona por ahora. Lo que hace esta función de búsqueda es, lo primero que queremos hacer es usar nuestra nueva función setState en la consulta para establecer setIsFetching en verdadero y borrar el error. Luego, en un bloque try-catch, intentaremos llamar a nuestra función de consulta, así que usaremos await aquí, obtendremos los data de la función de consulta, y luego si todo tiene éxito vamos a poner el estado de éxito y agregar nuestros data. Y luego en nuestro catch, si tenemos un error, vamos a hacer lo mismo, solo el estado de error con el error. Y finalmente, literalmente, finalmente, vamos a establecer queryPromise en nulo y query.setState vamos a establecer setIsFetching en falso.

Así que este quirky.promise aún no existe, pero lo vamos a necesitar. Así que vamos a establecer la promesa en nulo aquí arriba, desde el principio. Y lo que esto va a hacer es permitirnos comenzar a configurar algo de desduplicación. Así que si la función de consulta ya se está ejecutando o está en progreso, no queremos dispararla de nuevo. Así que vamos a usar esa propiedad query.promise para hacer algo de magia con las promesas. En lugar de hacer esta función Fetch async aquí, la vamos a envolver en otra lógica. La vamos a envolver en este bloque justo aquí. Así que si aún no hay una promesa, vamos a asignar esa promesa a una nueva promesa que viene de esta función asíncrona. Y podemos simplemente volcar toda nuestra lógica existente en esa función justo allí. Así que dice que si no hay una promesa, entonces inicia una nueva función Fetch y asígnala a la promesa. Y así que cualquier otra vez que llamemos a Fetch si ya hay una promesa, simplemente la vamos a devolver aquí mismo. Así que si no hay promesa, entonces diremos return query.promise. Y eso se encarga de nuestro problema de desduplicación, que es una forma bastante elegante y fácil de hacer eso. Queremos asegurarnos de que en el finally, cuando termine, establecemos esa promesa de consulta en nulo para que podamos dispararla de nuevo. Así que no podemos conectar esta función de creación de consultas directamente a nuestro hook useQuery. Tenemos que permitir que las consultas sean compartidas por múltiples instancias de useQuery, así que vamos a tener que crear algún soporte de suscripción para todo esto, y vamos a empezar a hacer eso en nuestra consulta, en nuestra función createQuery aquí. Voy a crear un nuevo método aquí llamado subscribe. Va a tomar un suscriptor, que por ahora es solo un objeto, y vamos a empujar eso en query.subscribers, así que voy a necesitar suscriptores aquí arriba que van a ser un array. Y luego va a devolver una función de cancelación de suscripción, que simplemente eliminará eso de la lista de suscriptores cuando lo llamemos. Y también necesitamos actualizar nuestra función setState aquí arriba para que cada vez que llamemos a setState notifiquemos a todos los suscriptores. Pasamos por ellos y llamamos a subscriber.notify. Y solo voy a mover esto aquí abajo, para mantener las cosas organizadas.

8. Almacenando y Recuperando Consultas con Query Client

Short description:

Necesitamos tener un lugar para almacenar estas consultas una vez que las creamos. Ahí es donde entra en juego el cliente de consulta. Configuramos un constructor para que cuando llamamos a newQueryClient establecemos this.queries a un array vacío. Configuraremos un nuevo método de clase llamado getQuery. Y getQuery va a obtener una consulta existente en esa lista o simplemente crear una y añadirla a ella y luego devolverla. Para hacer eso vamos a hacer un hash de la clave de consulta que estamos obteniendo de las opciones de aquí arriba y simplemente vamos a usar json.stringify para hacer eso, para obtener un hash de consulta.

Y ahora nuestra función createQuery se ve bastante bien, pero nos falta otra pieza vital. Necesitamos tener un lugar para almacenar estas consultas una vez que las creamos. Y ahí es donde entra en juego el cliente de consulta. Así que si subimos aquí al cliente de consulta, esto es solo una clase y podemos hacer esto realmente básico. Podemos simplemente configurar un constructor para que cuando llamamos a newQueryClient establecemos this.queries a un array vacío. Esto va a ser solo un array para todas nuestras consultas. Y vamos a configurar un nuevo método de clase aquí llamado getQuery. Y getQuery va a obtener una consulta existente en esa lista o simplemente crear una y añadirla a ella y luego devolverla. Así que está creando o obteniendo lo que le pedimos que construya para nosotros. Para hacer eso vamos a hacer un hash de la clave de consulta que estamos obteniendo de las opciones de aquí arriba y simplemente vamos a usar json.stringify para hacer eso, para obtener un hash de consulta. Una vez que tenemos ese hash, podemos intentar encontrar una consulta existente simplemente recorriéndolas y comparando los hashes. Si no tenemos una consulta ya aquí vamos a ejecutar nuestra función createQuery con las opciones que son solo la clave de consulta, la función de consulta, todas esas cosas. Pero tenemos que pasarle el cliente de consulta, también, con el que lo estamos creando. Así que vamos a bajar a createQuery y vamos a añadir aquí el cliente muy rápido para que esa firma coincida. Y luego empujamos esa consulta en this.queries para el cliente de consulta y luego la devolvemos. Así que, de todos modos, siempre estamos devolviendo una consulta aquí. Así que estamos creándola o agarrando una existente.

9. Conectando Consultas y Creando Observadores

Short description:

Necesitamos asegurarnos de que nuestra función createQuery soporte la clave de consulta y el hash de consulta. Necesitamos un observador de consulta para coordinar todas las suscripciones y usar consultas varias veces. El observador de consulta crea un objeto observador con los métodos notify, getResult y subscribe. El método subscribe toma un callback para volver a renderizar el componente y lo asigna a la propiedad observer.notify. Nos suscribimos a la consulta con el observador, obtenemos la función de cancelar suscripción y llamamos a query.fetch para habilitar la recuperación automática. En la función useQuery, obtenemos el cliente del contexto y trabajamos con el observador para manejar los datos.

Entonces, lo siguiente que necesitamos hacer es asegurarnos de que nuestra función createQuery soporte nuestra clave de consulta y el hash de consulta. Así que vamos a hacer que la clave de consulta se almacene allí y que el hash de consulta siempre esté dentro de allí para que podamos identificar la consulta.

Entonces, desde este punto, todavía estamos a un paso de conectar nuestras consultas a nuestro hook useQuery. Todavía necesitamos una cosa más en el medio para coordinar todas las suscripciones y asegurarnos de que podemos usar nuestras consultas varias veces en la aplicación y realmente solo crear una consulta. Así que vamos a hacer eso con algo llamado observador de consulta. Tengo una nueva función aquí llamada createQuery observer que es muy similar a la de arriba. Toma un cliente y alguna información de la consulta y va a crear un observador para nosotros. También va a crear una consulta aquí si es necesario.

Entonces vamos a llamar a createQuery observer. Va a obtener o crear la consulta y luego va a crear un nuevo objeto observador. Y este objeto observador tiene un par de métodos que vamos a revisar. El primero es notify que por ahora está vacío pero vamos a asignarlo a algo aquí en un segundo. El siguiente es getResult que simplemente nos va a dar el estado de las consultas que este observador está observando cuando lo llamamos. Y el tercero es subscribe. Este es el que vamos a llamar desde nuestro hook usedQuery. Así que vamos a pasarle un callback que probablemente será una función de renderizado para volver a renderizar nuestro componente cuando algo cambie. Simplemente vamos a tomar ese callback y asignarlo a nuestra propiedad observer.notify. Y luego vamos a suscribirnos a la consulta misma con este observador que estamos creando aquí. Y luego vamos a obtener la función de cancelar suscripción y devolverla. Y luego la parte más importante para habilitar nuestra recuperación automática es este query.fetch aquí. Cada vez que nos suscribimos a un nuevo observador queremos asegurarnos de que está iniciando una recuperación. Así que simplemente vamos a llamar a query.fetch aquí mismo. Y eso también se deduplicará bajo el capó. Así que finalmente con toda esta lógica podemos empezar a conectar nuestra función useQuery. Así que volvamos a useQuery y veamos cómo todo esto se junta. Claramente no vamos a devolver datos ficticios sino que vamos a hacer un montón de cosas con el observador que podemos crear dentro de aquí. La primera sección de esto aquí es que necesitamos saber con qué cliente estamos tratando. Y obtenemos eso del contexto que estamos usando aquí pasando a través de nuestro proveedor de contexto. Y lo vamos a recoger aquí mismo con react.useContext. Así que ahí está el cliente.

10. Lógica del Observador y Creación del Observador de Consulta

Short description:

Esta sección introduce la lógica del observador y la creación de un observador de consulta por instancia de useQuery. El observador se almacena en una ref y se inicializa con el cliente, la clave de consulta y la función de consulta obtenida de las opciones de useQuery.

Este próximo bloque aquí es solo una forma muy simple de volver a renderizar un componente en el que se está utilizando un hook. Así que solo una pequeña función de re-renderizado que podemos forzar al componente a volver a renderizar. La siguiente parte es la lógica del observador. Así que queremos almacenar este observador en esta ref y solo queremos crear un observador por instancia de useQuery. Así que si no existe, vamos a crear un observador de consulta. Le pasaremos el cliente que obtuvimos del contexto. Pasaremos la clave de consulta y la función de consulta que estamos obteniendo de nuestras opciones de useQuery. Y luego vamos a almacenar eso en la ref del observador.

11. Finalizando la Lógica del Observador

Short description:

Devolvemos la función getResult de nuestro observador, que devuelve el estado de la consulta. Nos suscribimos al observador y volvemos a renderizar nuestro componente cuando ocurren cambios. Funciona bien, con estados de carga y refetching en segundo plano. Pero todavía hay algunas cosas más que hacer.

A partir de ahí, vamos a devolver la función getResult de nuestro observador. Si recuerdas, devuelve el estado de la consulta. Así que va a devolver el estado de la consulta para lo que sea que el observador esté conectado. Y luego establecemos un efecto aquí, siempre que esto se monte, para que podamos suscribirnos a ese observador. Y cada vez que algo cambia en el observador, vamos a volver a renderizar nuestro componente que useQuery se está utilizando. Así que, técnicamente, esto debería funcionar justo ahora. Vamos a revisar nuestras líneas de code. Estamos en 130, y eso es genial. Si venimos aquí, las cosas deberían estar cargando, y puedes ver que está funcionando muy bien. Si recargamos la página, obtenemos ese estado de carga duro, pero solo para las primeras veces que estamos golpeando cosas. Y puedes ver que tenemos ese refetching en segundo plano que está sucediendo muy bien. Así que esto funciona muy bien ya, pero todavía tenemos algunas cosas más que necesitamos hacer.

12. Añadiendo Tiempo Estancado

Short description:

Necesitamos agregar tiempo estancado a nuestra función use query y crear un observador de consultas. Comprobaremos la última marca de tiempo actualizada y la compararemos con el valor del tiempo estancado. Si es mayor, iniciaremos una consulta de búsqueda. Después de habilitar el tiempo estancado en nuestra aplicación, podemos ver que la actualización en segundo plano solo ocurre después de que ha pasado el tiempo especificado.

Lo siguiente que necesitamos hacer es agregar tiempo estancado. Necesitamos ir a nuestra función use query aquí mismo, y simplemente vamos a agregar tiempo estancado. Y el tiempo estancado realmente necesita ser pasado hacia abajo, a través de nuestro create query observer aquí mismo. Así que iremos a nuestro create query observer, y lo recogeremos aquí mismo. Y el tiempo estancado simplemente se va a predeterminar a cero, así que vamos a predeterminarlo a cero aquí mismo. Luego lo que necesitamos hacer es reorganizar un poco esta lógica. Cuando nos suscribimos a un observador, en lugar de llamar a query.fetch, queremos hacer algunas comprobaciones primero. En lugar de hacer query.fetch, voy a llamar a algo llamado observer.fetch, y simplemente crearemos una nueva función aquí mismo en nuestro observador. Y este fetch va a tener alguna lógica condicional dentro de aquí, donde vamos a estar comprobando la última marca de tiempo actualizada de la consulta. Y vamos a tomar la fecha de ahora, o el tiempo ahora, menos nuestra última marca de tiempo actualizada, y si eso es mayor que nuestro tiempo estancado que hemos definido, vamos a iniciar el query.fetch. Y para que todo eso funcione, necesitamos ir a donde estamos estableciendo el éxito para nuestra consulta y asegurarnos de que añadimos esa marca de tiempo, última actualización. Dicho esto, deberíamos volver a nuestra aplicación, y vamos a activar el tiempo estancado para ambos y ver qué pasa. Si navegamos por ahí, no deberíamos estar obteniendo una actualización en segundo plano hasta que hayan pasado tres segundos. Y puedes ver que si vuelvo atrás, no lo vemos allí, pero lo veremos después de que hayan transcurrido los tres segundos. Así que el tiempo estancado está funcionando, y eso es genial.

13. Añadiendo Tiempo de Caché y Recolección de Basura

Short description:

Vamos a añadir tiempo de caché a nuestra función use query y crear un observador de consultas. Programaremos la recolección de basura para las consultas cuando se elimine el último suscriptor. El tiempo de caché se establecerá por defecto en cinco minutos. Estableceremos un tiempo de espera para el tiempo de caché y eliminaremos la consulta del cliente cuando expire. También añadiremos una forma de deshacer la recolección de basura y prevenirla cuando una consulta esté suscrita. Al añadir esta lógica, tendremos la recarga cuando volvamos a enfocar la ventana.

Lo siguiente que vamos a hacer es, veamos, nuestras líneas de code están en 142, así que estamos, oh, eso es React Querylight, 140. Así que estamos bastante cerca, pero aún podemos añadir algunas cosas más.

Lo último que vamos a hacer es el tiempo de caché. Así que el tiempo de caché también va a ser dirigido a través de use query. Vamos a hacer el tiempo de caché justo aquí. Y lo mismo, vamos a pasar eso a través de nuestra creación de observador, y vamos a recogerlo justo aquí, pero el tiempo de caché necesita ser dirigido un poco más allá. Así que vamos a pasar el tiempo de caché a través de la función get query aquí. Get query se pasa hasta aquí, las opciones se lanzan en la función create query, y aquí es donde lo recogemos. Y vamos a establecer eso por defecto en cinco minutos simplemente porque eso es lo que es en React Query. Así que eso es bastante divertido. Y este tiempo de caché es un poco más complicado, pero es bastante divertido.

Lo que necesitamos hacer es asegurarnos de que cuando se elimine el último suscriptor de una consulta que lo comprobamos y decimos que si no hay más suscriptores, vamos a programar una recolección de basura en esta consulta. Así que vamos a añadir esa función schedule GC. Simplemente la añadiremos aquí. Vamos a establecer un tiempo de espera que dure el tiempo de caché. Así que cuando el tiempo de caché se agote, vamos a eliminar esta consulta de nuestro cliente de consultas y a recogerla como basura. Vamos a necesitar esa variable de tiempo de espera de recolección de basura también. Así que vamos a añadirla aquí arriba y simplemente la estableceremos en null. Y también necesitamos una forma de deshacer esto también. Así que vamos a hacer un unschedule GC recolección de basura y eso simplemente va a borrar ese tiempo de espera si se llama, y queremos borrar eso si, en cualquier momento la consulta se suscribe. Así que simplemente lo haremos aquí. Cada vez que abrimos una nueva suscripción a una consulta queremos asegurarnos de que no va a ser recogida como basura más. Y eso honestamente debería ser todo lo que necesitamos. Así que si volvemos aquí y añadimos nuestro tiempo de caché de cinco segundos, lo que va a suceder es que si esperamos cinco segundos antes de cargar este post, esa lista principal de posts de nuevo, vas a ver un estado de carga duro aquí. Y eso es porque la consulta ya había sido recogida como basura de la lista después de cinco segundos.

Esas son todas las características base que hemos hablado. Y creo que tenemos tiempo para dos más que no explicaré demasiado, pero simplemente las meteremos ahí. Vamos a subir aquí al proveedor de cliente de consulta y simplemente meteremos esta lógica aquí. Y ahora, de repente, tenemos recarga cuando volvemos a enfocar la ventana. Así que no tenemos que estar navegando por ahí.

14. Herramientas de Desarrollo y Conclusión

Short description:

Podemos volver y quitar nuestro tiempo obsoleto y tiempo de caché, lo que hará esto un poco más evidente. Y cada vez que enfocamos la ventana, se va a actualizar en segundo plano. Tenemos un impresionante componente de herramientas de desarrollo aquí también. Las herramientas de desarrollo necesitan una forma de suscribirse al cliente de consulta en sí. Así que subiremos al cliente de consulta, añadiremos this.subscribers. Añadiremos un método de suscripción a esta clase que es muy similar a lo que hicimos con la consulta. Y luego también añadiremos un método de notificación aquí también, para que podamos llamar a notificar y notificar a cada suscriptor que necesita volver a ejecutarse. Puedes ver que nuestro post dice éxito, pasamos al siguiente, obtenemos una pequeña indicación de nuestra clave de consulta y éxito y este está inactivo pero si volvemos vuelve a entrar en juego. Si vamos por aquí y cargamos uno nuevo. Así que hay algunas herramientas de desarrollo. Realmente aprecio que hayan escuchado lo que tenía que decir hoy. Creo que React Query es una gran herramienta y estoy súper emocionado por lo que el futuro tiene reservado para React Query. En el corazón de React Query, realmente hay una impresionante comunidad de patrocinadores y contribuyentes y usuarios y personas que realmente han ayudado a hacer lo que es hoy y me gustaría decir gracias a todas esas personas.

Podemos volver y quitar nuestro tiempo obsoleto y tiempo de caché, lo que hará esto un poco más evidente. Y cada vez que enfocamos la ventana, se va a actualizar en segundo plano. Y luego también, tenemos un impresionante componente de herramientas de desarrollo aquí también. Simplemente voy a pegar todo el componente de herramientas de desarrollo. Y sé que estamos quedándonos cortos de tiempo, pero esto va a ser divertido. Así que busquemos las herramientas de desarrollo. Simplemente lo pondremos en la parte inferior. Herramientas de desarrollo realmente simples, pero sí depende de algunas cosas. Y solo necesitamos añadir esas cosas muy rápido.

Las herramientas de desarrollo necesitan una forma de suscribirse al cliente de consulta en sí. Así que subiremos al cliente de consulta, añadiremos this.subscribers. Añadiremos un método de suscripción a esta clase que es muy similar a lo que hicimos con la consulta. Y luego también añadiremos un método de notificación aquí también, para que podamos llamar a notificar y notificar a cada suscriptor que necesita volver a ejecutarse. Dicho esto, creo que solo necesitamos exportar nuestras herramientas de desarrollo de React Query. Y sabes qué, simplemente voy a subir la parte inferior de la ventana. Para que podamos verlo mejor. Y ahí están nuestras herramientas de desarrollo. Así que también necesitamos asegurarnos de que está notificando, veamos que tenemos set state aquí. Necesitamos asegurarnos de que también estamos notificando al cliente cuando establecemos el estado o si no las herramientas de desarrollo no se van a actualizar. Y probablemente deberíamos notificar al cliente en la recolección de basura también. Así que hagámoslo ahí. Ahí vamos. Puedes ver que nuestro post dice éxito, pasamos al siguiente, obtenemos una pequeña indicación de nuestra clave de consulta y éxito y este está inactivo pero si volvemos vuelve a entrar en juego. Si vamos por aquí y cargamos uno nuevo. Así que hay algunas herramientas de desarrollo.

Sé que se nos acabó el tiempo así que volvamos y terminemos las cosas aquí. Realmente aprecio que hayan escuchado lo que tenía que decir hoy. Creo que React Query es una gran herramienta y estoy súper emocionado por lo que el futuro tiene reservado para React Query. En el corazón de React Query, realmente hay una impresionante comunidad de patrocinadores y contribuyentes y usuarios y personas que realmente han ayudado a hacer lo que es hoy y me gustaría decir gracias a todas esas personas. Asegúrate de venir a hablar conmigo un poco más en el chat.

QnA

Discusión y Preguntas y Respuestas

Short description:

Siempre estoy abierto a una buena charla. Discutamos algunos de los resultados de la encuesta. Tenemos algunas preguntas increíbles de la gente en el Discord. Por cierto, fue una charla muy divertida. Repasemos estas preguntas de la audiencia. Aprilian pregunta, ¿la API V3 va a permanecer estable al menos unos meses más o debería esperar a la V4 antes de migrar proyectos existentes entre versiones mayores? Definitivamente es estable. Deberías actualizar ahora. Pero si lanzamos una V4, no va a haber grandes cambios disruptivos como lo fue con la V3. Serán pequeños. Vamos a tomarlo con calma de aquí en adelante. Así que no te preocupes.

Siempre estoy abierto a una buena charla. Puedes encontrarme en tanstack.com, nozel.io, y mi nombre de usuario es tannerlindsley en casi todos los demás lugares. Así que, gracias. Genial, esa fue una charla muy interesante. Muchas gracias, Tanner.

Discutamos algunos de los resultados de la encuesta. Entonces, Tanner quería saber si has usado React Query antes y el 68% dijo que aún no lo han probado, pero el 25% lo está usando ahora y el 7% lo usó antes. Tenemos algunas personas experimentadas con React Query en la audiencia. Recibimos algunas preguntas increíbles de la gente en el Discord. Por cierto, fue una charla muy divertida. Estoy muy impresionado por tus habilidades de codificación en vivo. Los gremlins siempre aparecen cuando hago demostraciones en vivo, así que siempre es impresionante ver a la gente escribiendo code en vivo y que realmente funcione. Es mucho más fácil cuando solo estás pegando cosas. Ese es el truco. El desarrollo impulsado por copiar y pegar es real. Si hubiera ido letra por letra, no habríamos terminado a tiempo. Genial.

Vale. Así que repasemos estas preguntas de la audiencia. Entonces Aprilian pregunta, ¿la API V3 va a permanecer estable al menos unos meses más o debería esperar a la V4 antes de migrar proyectos existentes entre versiones mayores? Definitivamente es estable. Va a permanecer así por un tiempo. Deberías actualizar ahora. Pero si lanzamos una V4, no va a haber grandes cambios disruptivos como lo fue con la V3. Serán pequeños. Vamos a tomarlo con calma de aquí en adelante. Así que no te preocupes. Genial. Entonces, esa es una respuesta bastante definitiva. Usa la V3. Este nombre de usuario es complicado.

Herramientas de React Native y Pruebas

Short description:

ALBSKJORR pregunta sobre las herramientas de desarrollo de React Native para ReactQuery. No conozco la fecha de lanzamiento. Jordie VD pregunta sobre los beneficios de ReactQuery sobre Apollo para GraphQL. ReactQuery es más fácil de entender, pero carece de la experiencia de primera clase de GraphQL. La forma sugerida de probar componentes usando UseQuery es con la Biblioteca de Pruebas de React. Publicaré el código en mi GitHub, pero no está listo para producción.

ALBSKJORR pregunta, ¿cuándo se lanzarán las herramientas de desarrollo de React Native para ReactQuery? No lo sé. No estoy trabajando en ellas. No puedo usar React Native ahora mismo. Así que espero que eso responda a tu pregunta. Yo tampoco. Deberías construirlas. Quien haya hecho esa pregunta, debería intentar construirlas. Eso sería genial. Eso sería realmente genial. Sí, nunca he hecho nada de desarrollo móvil, lo cual probablemente debería hacer en algún momento. Ni siquiera he probado React Native y Flutter.

Jordie VD pregunta, ¿tendría ReactQuery beneficios sobre algo como Apollo cuando se usa GraphQL? He oído a la gente decir que ReactQuery es más fácil de entender y manipular. Su API es un poco más simple, pero no tiene la experiencia de primera clase de GraphQL como la que obtendrías con Apollo o ... Así que no obtendrías la experiencia de primera clase que tendrías con Apollo o Urql. Genial.

Tenemos tiempo para una pregunta más y luego cualquier persona que tenga una pregunta restante, Tara estará en el chat espacial para responder más. Así que si quieres unirte allí, puedes hacer tu pregunta, incluso si no llegamos a ella aquí. Y la última pregunta es, ¿cuál es la forma sugerida de probar componentes usando UseQuery por MHI? Biblioteca de Pruebas de React. Pruébalo como lo usarías en tu aplicación. Puedes mirar las pruebas de React Query en sí mismas. Usamos la Biblioteca de Pruebas de React y no probamos ningún detalle de implementación. Así que hazlo así. Ahí lo tienes, genial, genial. Otro que haré muy rápido porque es un sí o un no, ¿publicarías el código para esto? Sí. Haré lo posible por publicar el código en mi GitHub. Genial. Genial. Pero escuchaste en la presentación que no uses este código. No está listo para producción. Sí, no uses este código. Si lo publico, no lo uses y por favor no me preguntes si es seguro para el modo concurrente o suspense listo. Genial, genial. Genial. Así que de nuevo, únete a Tanner en la sala de conferencias en el chat espacial y el enlace para unirte a eso está en la línea de tiempo.

Check out more articles and videos

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

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
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. 
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Summit Remote Edition 2020React Summit Remote Edition 2020
30 min
React Query: It’s Time to Break up with your "Global State”!
Top Content
An increasing amount of data in our React applications is coming from remote and asynchronous sources and, even worse, continues to masquerade as "global state". In this talk, you'll get the lowdown on why most of your "global state" isn't really state at all and how React Query can help you fetch, cache and manage your asynchronous data with a fraction of the effort and code that you're used to.

Workshops on related topic

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

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

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

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

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