React Query: ¡Es hora de romper con tu "Estado Global"!

Rate this content
Bookmark

Una cantidad cada vez mayor de datos en nuestras aplicaciones de React proviene de fuentes remotas y asíncronas y, lo que es peor, continúa disfrazándose como "estado global". En esta charla, obtendrás toda la información sobre por qué la mayoría de tu "estado global" en realidad no es estado en absoluto y cómo React Query puede ayudarte a obtener, almacenar en caché y gestionar tus datos asíncronos con una fracción del esfuerzo y código al que estás acostumbrado.

30 min
02 Aug, 2021

Video Summary and Transcription

Se discute la gestión del estado global y los desafíos de colocar el estado del servidor en el estado global. React Query se presenta como una solución para manejar el estado asíncrono del servidor. La charla demuestra el proceso de extraer la lógica en hooks personalizados y solucionar problemas con el estado y la lógica de obtención. Se muestran las actualizaciones optimistas con mutaciones, junto con los beneficios de usar React Query para la obtención y mutación de datos. Se discute el futuro de la gestión del estado global, junto con los comentarios de los usuarios sobre React Query. La charla concluye con una invitación a explorar React Query para la gestión del estado del servidor.

Available in English

1. Introducción a la Gestión del Estado Global

Short description:

Hola, soy Tanner Linsley, cofundador y VP de UI y UX en nozzle.io. Hoy quiero hablar sobre la gestión del estado global y el error de colocar el estado del servidor en el estado global. El estado del servidor es diferente del estado del cliente en términos de almacenamiento, velocidad de acceso y propiedad. Veamos por qué y cómo podemos manejar el estado del servidor de manera más efectiva.

Hola a todos. Mi nombre es Tanner Linsley y soy cofundador y VP de UI y UX en nozzle.io, donde desarrollamos software de seguimiento de clasificación en motores de búsqueda para empresas. Me encanta React y JavaScript y también tengo una obsesión por construir software de código abierto.

Desde que aprendí React, he estado muy obsesionado con temas como la generación de sitios estáticos, la visualización de datos y la animación. Pero hoy me gustaría hablarles sobre lo que posiblemente es mi favorito de todos, la gestión del estado global.

Hoy en día, una gran cantidad de código en nuestras aplicaciones se dedica a consumir y manipular datos asincrónicos. Ya sea que estos datos provengan de nuestros usuarios, servidores o APIs de terceros, es absolutamente fundamental que nuestras aplicaciones brinden valor a nuestros usuarios. De hecho, para muchos de nosotros, nuestras aplicaciones son simplemente interfaces de usuario opinionadas para consumir y gestionar estos datos.

A lo largo de los años, he notado que los patrones para acceder y manipular nuestros datos en nuestras aplicaciones se han establecido rápidamente en lo que todos conocemos como estado global. El estado global es muy conveniente. Nos ayuda a evitar la propagación de props y nos permite acceder a los datos en toda nuestra aplicación sin copiarlos ni duplicarlos. Incluso nos ayuda a comunicarnos entre componentes y hooks aislados que de otra manera no podrían hacerlo. Al final, simplemente nos ayuda a hacer más con menos código. Es extremadamente accesible y poderoso, por lo que es natural que queramos que todos nuestros datos importantes del lado del servidor sean tan accesibles como nuestro estado global. Y con esa expectativa, no es sorprendente que nosotros, como desarrolladores de React, hayamos elegido colocar nuestros datos del lado del servidor junto con el resto de nuestro estado global.

Es relativamente fácil hacer esto utilizando algo como el estado local del componente con el contexto de React, o incluso utilizando cualquiera de las numerosas bibliotecas de herramientas de gestión del estado global que existen. Pero al final, la expectativa suele ser la misma. Esperamos que nuestro estado global no solo pueda manejar cosas triviales como el estado del menú, temas, cosas como toasts y alertas, sino que también esperamos que sea responsable de los ciclos de vida complejos en torno a la obtención y provisión de nuestros datos del lado del servidor y asíncronos a nuestros usuarios.

Así que hoy, estoy aquí para decirles que a pesar de la conveniencia fugaz que nos brinda el estado global al trabajar con datos del lado del servidor, creo que hemos cometido un error muy grande al colocarlo allí. Nos hemos engañado a nosotros mismos y a nuestro código al pensar que todo el estado es igual, cuando creo que nuestros datos asíncronos y el estado global no podrían ser más diferentes, especialmente cuando se trata de dónde se almacenan, la velocidad a la que los accedemos y cómo los accedemos y actualizamos, y en última instancia, quién puede realizar cambios en ellos.

Para que todo esto sea más fácil de entender, quiero dejar de usar el término estado global y en su lugar llamar a estos dos tipos diferentes de estado: estado del cliente y estado del servidor. El estado del cliente es relativamente simple y debería ser familiar para la mayoría de los desarrolladores. Es temporal y local, y generalmente no se persiste entre sesiones. Se accede a él con APIs síncronas que no tienen latencia, y la mayoría de él es propiedad de la instancia de la aplicación del cliente. Por todas estas razones, podemos confiar en que nuestro estado del cliente siempre estará actualizado en cualquier momento de nuestra aplicación.

Sin embargo, el estado del servidor es bastante diferente. El estado del servidor se almacena de forma remota, por lo que la ubicación de la fuente de verdad para nuestro estado del servidor es potencialmente desconocida, o al menos está fuera de nuestro control. Es asíncrono, por lo que tenemos que acceder a él con APIs asíncronas, y también tiene una propiedad compartida implícita, lo que significa que no solo es propiedad de nuestro cliente. Puede ser leído y manipulado tanto por el servidor como por cualquier otro cliente potencial que interactúe con él. Debido a todas estas cosas, en realidad se pueden hacer muy pocas garantías sobre nuestro estado del servidor siempre estando actualizado en nuestras aplicaciones, y en su lugar generalmente terminamos confiando solo en instantáneas de nuestros datos asíncronos.

2. Estado del Servidor y Estado del Cliente

Short description:

Cuando el estado del servidor y el estado del cliente se almacenan en el mismo sistema, se hacen compromisos. El estado del servidor tiene desafíos únicos que requieren herramientas dedicadas. React Query es una biblioteca de NPM que resuelve el estado asincrónico del servidor con una API pequeña y simple. Para demostrar sus capacidades, construí una aplicación de blog con React y Next.js. La aplicación permite ver, editar y agregar publicaciones. Inicialmente, la aplicación tenía cuatro componentes principales, cada uno usando useEffect y React State para la obtención de datos y los estados de carga. Sin embargo, quería hacer el código más portable.

Entonces, cuando tomamos estos dos tipos de estado muy diferentes, el estado del servidor y el estado del cliente, y tratamos de almacenarlos en el mismo sistema, eventualmente haremos compromisos que favorecen a uno u otro. Un buen ejemplo de esto es que el estado del servidor tiene sus propios desafíos únicos que nunca enfrentamos con el estado del cliente. Algunos ejemplos de esto podrían ser cosas como el almacenamiento en caché, la deduplicación de solicitudes, la actualización de datos en segundo plano, el manejo de solicitudes desactualizadas, el manejo de mutaciones, la paginación y la obtención incremental, e incluso la recolección de basura, la gestión de errores de memoria y todo lo demás que implica el almacenamiento en caché en general. Muchos patrones de estado global no ofrecen soluciones para este tipo de desafíos, o al menos intentan resolverlos con APIs complicadas o sistemas de complementos sobreingenierados, y a veces incluso APIs demasiado potentes que son básicamente armas de doble filo para el desarrollador promedio de React.

Tanto el estado del servidor como el estado del cliente claramente necesitan mucho amor, pero cada uno lo necesita a su manera. Y aunque creo que tienen algunas cosas en común en cuanto a cómo los accedemos en nuestras aplicaciones, creo que es hora de que el estado del servidor y el estado del cliente se separen. Hay mucho más en el estado del servidor que simplemente ser accesible globalmente, y creo que merece nuevas herramientas dedicadas que no solo resuelvan estos desafíos, sino que los manejen automáticamente de una manera elegante. Por eso decidí construir React Query. React Query es una biblioteca de NPM compuesta por un par de hooks y utilidades que tienen como objetivo resolver el estado asincrónico del servidor. Es una API pequeña, simple y está diseñada para ayudar tanto a los desarrolladores de React novatos como avanzados a tener éxito sin requerir una configuración mínima o nula.

Para realmente comprender cómo React Query puede transformar drásticamente la forma en que manejas el estado del servidor, decidí construir una pequeña aplicación de blog interactiva utilizando React y una pequeña API impulsada por Next.js. El propósito de esta aplicación es bastante simple. Muestra una lista de publicaciones, nos permite ver una vista detallada de una publicación individual y luego nos permite editar las publicaciones existentes o agregar nuevas también. Voy a mostrarles algunas etapas o confirmaciones que hice en este proyecto de cómo evolucionó la gestión del estado de esta aplicación en la práctica y cómo, al final, finalmente pude usar React Query para salvar el día.

Entonces, primero, familiaricémonos con la aplicación. Tenemos una barra lateral confiable con un solo enlace a nuestra página de publicaciones. Tenemos una página de publicaciones que obtiene todas nuestras publicaciones de nuestra API y las muestra en una lista. Podemos hacer clic en una publicación y cargar la vista detallada con el contenido completo. Podemos usar el formulario de edición en la parte inferior para editar la publicación. Y luego, en nuestra lista de publicaciones, podemos usar ese mismo formulario para agregar una nueva publicación a la lista. Para hacer todo esto, nuestra aplicación comenzó con cuatro componentes principales. Un componente de aplicación, que maneja todas nuestras rutas y el estado de enrutamiento. Un componente de publicación, que obtiene nuestras publicaciones de la API y luego las muestra con el formulario de agregar nueva publicación debajo de ellas. Un componente de publicación individual que obtiene el contenido completo de una publicación y lo muestra y luego nos da el formulario de edición en la parte inferior. Y finalmente, tenemos un componente de formulario de publicación reutilizable que solo se utiliza para editar los campos de la publicación. En cada uno de estos componentes de publicación, actualmente estamos utilizando una estrategia de useEffect para llamar a una función asíncrona y obtener nuestros datos. Luego usamos el estado de React para realizar un seguimiento de los estados de carga de esas solicitudes. De esta manera, cuando montamos cada uno de esos componentes, se solicitan los datos y eventualmente se representan en nuestra interfaz de usuario. Todo esto está bien y funciona, pero personalmente no me gusta tener mucha lógica de negocio en mis componentes. Así que quiero ver si podemos hacer esto un poco más portable.

3. Extrayendo la Lógica en Hooks Personalizados

Short description:

En el siguiente commit, he extraído la lógica para obtener datos en hooks personalizados. Esto nos permite reutilizar los hooks en toda nuestra aplicación. Sin embargo, estamos experimentando un problema donde el endpoint de publicación se llama dos veces. Esto se debe a que cada vez que usamos el hook, se crea una nueva instancia de estado y efectos, lo que resulta en solicitudes duplicadas de datos.

En este siguiente commit, he extraído toda la lógica para obtener nuestros data y los he colocado en sus propios hooks personalizados. Entonces, los hooks 'usePosts' y 'usePostFiles' ahora contienen toda la misma lógica y estado para obtener nuestras listas de publicaciones y detalles de publicaciones, pero combinados en un hook personalizado. Y también he movido toda la lógica para nuestras mutaciones en nuevos archivos llamados 'useCreatePost' y 'useSavePost' que funcionan de manera similar. Esto libera a nuestros componentes de la necesidad de definir toda la lógica ellos mismos y simplemente enfocarse en renderizar la interfaz de usuario, lo cual, en mi opinión, es un gran patrón independientemente de cómo se gestione el estado.

Ahora que tenemos nuestra lógica de obtención dentro de estos hooks reutilizables, podemos usarlos en cualquier otro lugar de nuestra aplicación que queramos. Además, en este commit, agregué un pequeño contador de publicaciones totales en nuestra barra lateral que llama al mismo hook 'usePosts' nuevamente para mostrar el recuento total de publicaciones. Así que con toda esta abstracción, puede parecer una gran ventaja para la reutilización de código. Pero si miramos nuestra pestaña de red, veremos que algo extraño está sucediendo. Nuestro endpoint de publicación se llama dos veces, una vez para la lista de publicaciones y nuevamente para el contador total de publicaciones. Aunque hemos extraído el estado en hooks reutilizables, no significa realmente que los data dentro de ellos sean reutilizables en sí mismos. La verdadera razón de esto es porque cada vez que usamos nuestro hook 'usePosts', creamos una nueva instancia de estado y efectos cada vez que lo renderizamos. Entonces, si seguimos así, estaremos solicitando duplicadamente una tonelada de data para nuestra aplicación una y otra vez cada vez que usemos ese hook.

4. Solucionando el Estado y la Lógica de Obtención

Short description:

En el siguiente commit, te mostraré cómo solucionar el problema convirtiendo el estado y la lógica de obtención en nuestros hooks en componentes globales que se renderizan una vez para toda la aplicación. Al crear un componente raíz para la lista de publicaciones y mover la lógica de obtención allí, podemos tener un único lugar para obtener la lista de publicaciones. Utilizaremos un objeto de contexto para pasar el estado y la lógica a lo largo del árbol de componentes, permitiendo que nuestro hook 'usePosts' acceda a la lista de publicaciones global. Veamos si esto resuelve nuestro problema.

En este siguiente commit, te mostraré cómo intento solucionar eso convirtiendo parte del estado y la lógica de obtención en nuestros hooks en componentes globales que solo se renderizan una vez para toda la aplicación. Así que he creado un componente raíz para nuestra lista de publicaciones y he movido toda la lógica de obtención a ese componente. De esta manera, tenemos un único lugar donde puede ocurrir la obtención de la lista de publicaciones para toda nuestra aplicación, siempre y cuando lo rendericemos en la raíz y solo lo rendericemos una vez. Dado que solo podemos renderizarlo una vez, tenemos que tomar todo ese estado y lógica y enviarlo a lo largo de nuestro árbol de componentes de React a través de un objeto de contexto. De esta manera, en nuestro hook 'usePosts', podemos suscribirnos a ese contexto y acceder a nuestra lista de publicaciones global para nuestra aplicación. Así que vamos a ver si eso resolvió nuestro problema.

5. Solucionando las Solicitudes Duplicadas

Short description:

Nuestro punto final de publicaciones todavía está siendo solicitado duplicadamente debido a que el hook 'usePosts' obtiene los datos para cada instancia. Para solucionar esto, utilizamos una referencia de React para rastrear las promesas y reutilizamos la promesa de la solicitud original para las solicitudes posteriores. Esto garantiza que se realice una única solicitud y que los componentes se carguen simultáneamente.

No, no lo hizo. Parece que nuestro punto final de publicaciones todavía está siendo solicitado duplicadamente. Esto puede parecer extraño, pero en realidad es porque cada vez que cargamos nuestro hook 'usePosts', necesitamos asegurarnos de que esté obteniendo los data para que esté actualizado para el componente que lo va a utilizar. Pero esto también significa que cada instancia va a llamar a la función de obtención cada vez que se monte, incluso si se montan al mismo tiempo. Afortunadamente, conozco una forma de solucionar esto, y de todos modos necesitábamos el estado global, así que al menos no perdimos nuestro tiempo con eso.

En el siguiente commit, te mostraré la forma más fácil que conozco para eliminar las solicitudes asíncronas duplicadas que ocurren al mismo tiempo. Comenzamos utilizando una referencia de React para rastrear la promesa de cualquier solicitud saliente. Luego, si se realizan otras solicitudes mientras la promesa aún está pendiente, simplemente reutilizamos la promesa de la solicitud original para no enviar solicitudes adicionales, y cada función asíncrona aún puede resolverse cuando llegue la solicitud original. Y si volvemos a nuestro panel de red ahora, verás que solo hay una solicitud para nuestro punto final de publicaciones, y tanto la lista de publicaciones como el contador total de publicaciones se cargan al mismo tiempo, lo cual es genial.

6. Agregando Búsqueda de Publicaciones y Estado Individual de Publicación

Short description:

En este siguiente commit, he agregado un cuadro de búsqueda en la barra lateral para buscar publicaciones por ID. El estado de detalle de la publicación ahora almacena estados separados para cada detalle, incluyendo estado, datos, error y referencia de promesa. Esto permite que tanto la vista de detalle como la barra lateral se actualicen simultáneamente y compartan la misma solicitud.

Hasta este punto, hemos prestado mucha atención a nuestra lista de publicaciones. Cambiemos de tema y veamos nuestra vista de publicación individual. Es genial que podamos hacer clic en una publicación para ver su contenido, pero sabía que eventualmente necesitaría una forma de buscar una publicación por su ID, lo cual no puedo hacer con esta interfaz de usuario todavía. Así que en este siguiente commit, he agregado un pequeño cuadro de búsqueda en mi barra lateral que me permite ingresar un ID de publicación y consultar mi API. Simplemente tomaremos un ID de una de estas publicaciones, lo pondremos aquí en el cuadro de búsqueda. Si se encuentra la publicación, muestra el título y me permite hacer clic para abrir la publicación, lo cual es genial. Pero poco después de agregar esta función, noté algo extraño que sucedía cuando editaba una publicación que también tenía cargada en la barra lateral.

Entonces, si editamos esta publicación, el detalle de la publicación se recarga con el título correcto, pero la barra lateral se queda atascada con el antiguo. Y la forma en que está estructurada nuestra aplicación en este momento, no hay realmente una buena forma de forzar a esa barra lateral a recargarse sin introducir un poco más de estado global. Fue bastante fácil convertir nuestra lista de publicaciones en estado global, así que pensé que no debería ser mucho más difícil hacerlo con el estado individual de la publicación también. Y luego, en este siguiente commit, te mostraré algunas dificultades con las que me encontré, que no tuve que preocuparme en el estado de la lista de publicaciones, pero cómo las solucioné. Lo que sucedió aquí es que nuestro estado de detalle de la publicación en realidad necesitaba almacenar un estado separado para cada detalle diferente que estábamos solicitando al servidor, incluyendo estado, data, error e incluso su propia pequeña referencia de promesa para poder rastrear y deduplicar promesas a nivel de detalle de la publicación. Fue un poco más de trabajo, pero funcionó bien. Y funciona tan bien como nuestro estado global de la lista de publicaciones. Y ahora puedes ver que si tomamos un ID de publicación, lo buscamos en nuestra barra lateral, intentamos actualizar el título, tanto la vista de detalle como la de la barra lateral se actualizarán y compartirán la misma solicitud. Así que definitivamente es más consistente que antes.

7. Mejorando la Obtención de Datos y las Mutaciones

Short description:

Aunque hemos avanzado con el estado global, todavía hay problemas con los estados de carga. React Query resuelve estos problemas al manejar el almacenamiento en caché y la recarga en segundo plano. Simplifica la obtención de datos y reduce el código. Las mutaciones, como agregar y editar publicaciones, ya no activan estados de carga innecesarios.

Y aunque siento que hemos logrado bastante hasta este punto, con la adición del estado global y todo eso, todavía hay un par de problemas en este momento que me molestan. En primer lugar, creo que se muestran demasiados estados de carga. Y honestamente, después de todo el trabajo duro que acabamos de hacer con el estado global, fue un poco decepcionante que todos los estados de carga siguieran ocurriendo.

Otra cosa es que cuando activamos una búsqueda de una de nuestras publicaciones, como con la búsqueda en la barra lateral, mientras también estamos viendo la misma publicación en la vista detallada, la vista detallada también entra en un estado de carga cuando realmente no es necesario. Y honestamente, se siente como una mala experiencia de usuario. Y luego, las otras cosas que ni siquiera hemos analizado aún son cosas como el almacenamiento en caché, la paginación y ni siquiera quiero pensar en cómo podríamos acceder de forma síncrona a nuestro estado global en este momento para hacer actualizaciones optimistas en nuestras mutaciones. Así que podríamos seguir en esta locura de intentar adaptar el estado global a nuestra voluntad y manejar todos estos casos especiales. Pero puedes creerme que se vuelve bastante complicado muy rápidamente. Incluso para los administradores de estado global más avanzados que existen, se vuelve bastante loco.

Y con eso dicho, finalmente creo que es hora de que React Query entre en acción y salve el día. Así que en este próximo commit, he trasladado todos nuestros hooks de obtención de datos para usar React Query en lugar de nuestro estado global y la lógica de useEffect. Y como puedes ver, pudimos eliminar alrededor de 150 líneas de código de nuestros hooks de publicaciones y también reemplazarlos con unas pocas líneas del hook useMutation de React Query, o no, el hook useQuery. Todo lo que tuvimos que hacer fue obtener una clave única para nuestros datos y la función asíncrona para obtenerlos. Así que veamos cómo funciona eso.

Está funcionando correctamente. Y honestamente, se siente mucho más rápido a medida que nos movemos por la aplicación, especialmente para las vistas y publicaciones que ya hemos visitado. Y esto se debe principalmente a que React Query maneja automáticamente el almacenamiento en caché y la recarga en segundo plano de forma predeterminada. Y cuando las cosas están en caché, se pueden renderizar de inmediato la próxima vez que se vean. Y honestamente, a veces puede parecer un poco irreal, como cuando buscamos una publicación en nuestra barra lateral y hacemos clic en el enlace. Dado que la publicación ya está en caché desde la búsqueda en la barra lateral, la vista detallada se carga al instante. Incluso notarás un pequeño estado de actualización en la parte superior que nos indica que se estaba obteniendo y recargando en segundo plano, aunque se recargó de inmediato.

Así que esto es realmente genial. La obtención de datos funciona mucho mejor y pudimos eliminar una tonelada de código. Ahora quiero ver cómo funcionan y cómo se sienten nuestras mutaciones. Ahora agregar una publicación es mucho mejor porque no entra en el estado de carga para obtener la nueva publicación. Y ni siquiera, bueno, y simplemente se recarga en segundo plano y se agrega al final de la lista. Así que ya no tenemos ese estado de carga brusco que teníamos antes. Y lo mismo ocurre con la edición de una publicación. Ya no veremos ese estado de carga tampoco.

8. Actualizaciones Optimistas con Mutaciones

Short description:

En este próximo commit, te mostraré cómo usar mutaciones para realizar algo llamado actualizaciones optimistas. Son una excelente manera de hacer que tu interfaz de usuario se sienta rápida, incluso cuando trabajas con datos asíncronos. Al usar los callbacks onMutation y onError, junto con la caché de consultas de React Query, podemos actualizar optimistamente nuestra interfaz de usuario y volver a un valor anterior si la mutación falla. Si tiene éxito, activamos una recarga en segundo plano para asegurarnos de ver el estado real del servidor. Observa detenidamente cómo uso el formulario de publicación de anuncios para ver esto en acción. Nuestra aplicación ahora es increíble.

Verás que ocurre una actualización en segundo plano y aparecerá un nuevo título. Incluso con este nuevo botón que agregué para eliminar una publicación, nos lleva de vuelta a la página de la publicación sin mostrarnos un estado de carga y simplemente activa una actualización en segundo plano, lo cual es genial. Quiero decir, honestamente, todo esto es realmente increíble considerando que en este momento nuestras mutaciones todavía son bastante ingenuas. De hecho, cuando ejecutamos nuestras mutaciones en nuestros componentes de interfaz de usuario en este momento, todavía tenemos que asegurarnos de llamar a la función de recarga para cualquier consulta que necesitemos actualizar en segundo plano. Y aunque eso funciona, hay una forma mucho más fácil de hacerlo que te mostraré en este próximo commit. En este próximo commit, también migro todos nuestros hooks de mutación a React Query. Y la forma en que lo hacemos es con el hook useMutation. El hook useMutation nos ayuda a eliminar, una vez más, una gran cantidad de código que se dedicaba a manejar el estado de la mutación y lo reemplaza con una sola llamada a useMutation. Luego podemos pasar nuestra función de mutación asíncrona a eso. Incluso si eso es todo lo que hicimos, simplemente deshacernos de una gran cantidad de código, estaría contento con eso. Pero useMutation tiene un par de opciones más que nos ayudan a hacer mucho más. La más obvia que puedes ver aquí es onSuccess, que es simplemente una función que he pasado y que se llama cada vez que nuestra mutación tiene éxito. Dentro de esa devolución de llamada, podemos usar otra importación de React Query llamada la caché de consultas para notificar a cualquier consulta relacionada que deben volver a cargarse. Y dado que lo estamos haciendo allí, toda la lógica de recarga en nuestros componentes ha desaparecido. Simplemente podemos definir declarativamente nuestras dependencias de mutación una por una dentro de nuestra mutación en lugar de tener que llamar manualmente a todas las consultas para volver a cargar cada vez que ejecutamos una mutación en nuestros componentes de interfaz de usuario. Hasta este punto, estas cosas no han hecho realmente nada diferente para nuestra interfaz de usuario aparte de hacer que el código sea más mantenible. Y al final del día, todavía estamos lidiando con un servidor que tarda uno o dos segundos en aplicar nuestros cambios y devolvernos lo que necesitamos volver a cargar. Para mí, y probablemente para todos ustedes también, esos pocos segundos pueden parecer una eternidad. Entonces digo, ¿qué tal si podemos predecir el futuro? ¿Qué tal si podemos configurar nuestro estado para que muestre lo que esperamos que muestre después de que el servidor haya terminado, pero hacerlo de inmediato? En este próximo commit, rápidamente te mostraré cómo usar mutaciones para hacer algo llamado actualizaciones optimistas. Son una forma realmente genial de hacer que tu interfaz de usuario se sienta realmente rápida, como si ni siquiera estuvieras trabajando con datos asíncronos. Y useMutation tiene un par de opciones que podemos pasarle, como el callback onMutation, que se ejecuta antes de que se ejecute nuestra función de mutación. El callback onError, que se llama cuando nuestra función de mutación falla. Y si combinamos todo eso con la caché de consultas de React y su capacidad para leer y escribir datos desde nuestra caché de forma síncrona, podemos actualizar optimistamente nuestra interfaz de usuario. Y luego, en caso de que la mutación falle, simplemente podemos volver a un valor anterior. Y si tiene éxito, podemos activar una recarga en segundo plano para asegurarnos de ver el estado real del servidor en lugar de solo una suposición. Así que si observas detenidamente, mientras uso este formulario de publicación de anuncios aquí, verás que hace exactamente eso. Hay un 50-50 de posibilidades de que falle. Así que a veces tiene éxito y a veces falla. Pero puedes ver que nuestra interfaz de usuario se deshace mágicamente o se actualiza cada vez que ocurre cada escenario. Nuestra aplicación ahora es increíble.

9. El Futuro de la Gestión del Estado Global

Short description:

React Query es el futuro para manejar datos asíncronos y resolver los desafíos con el estado del servidor. Nos ayuda a modelar y pensar en el estado global con una nueva perspectiva y, en algunos casos, eliminarlo de nuestra aplicación.

Se siente genial. Es muy rápido. Y también es muy mantenible. Pero todos ustedes vieron que cuando comenzamos esta aplicación, era rápido y familiar saltar entre esos patrones de IU comunes en los que nos apoyamos cuando lidiamos con el estado global. Y aunque podemos dedicar mucho esfuerzo a esos patrones de estado global, muchas cosas pueden salirse de control bastante rápido. Por eso, creo que herramientas como React Query son el futuro para manejar nuestros datos asíncronos. No solo resuelven los desafíos con el estado del servidor, sino que también nos ayudan a modelar y globalizar nuestro estado global y pensar en él con una nueva perspectiva. Y en algunos casos, incluso lo eliminan por completo, o al menos la mayor parte, de nuestra aplicación.

10. Opiniones de los usuarios sobre React Query

Short description:

He recibido excelentes comentarios sobre React Query de los usuarios. Kent C. Dodds dijo que es la pieza que faltaba para el desarrollo de aplicaciones React. Marcelo Alves adora reemplazar Redux con React Query. Demetrius Clark encuentra que ayuda a mantener un flujo de trabajo productivo y la afinación de la interfaz de usuario. React Query es ahora su gestor de estado de servidor preferido.

He recibido muchos comentarios de personas que han utilizado React Query, y la gente tiene grandes cosas que decir al respecto. Me gustaría compartir algunas rápidas y divertidas con ustedes. Mi amigo Kent C. Dodds dijo que React Query es la pieza que faltaba para el desarrollo de aplicaciones React que he estado buscando después de años de construir aplicaciones React. Finalmente, tengo una herramienta que me brinda exactamente lo que necesito para resolver los problemas de gestión del estado de mi aplicación sin darme más problemas. Es fantástico. Marcelo Alves dijo: todavía me gusta mucho Redux, pero cada vez que elimino una parte del almacenamiento y la reemplazo con React Query, es una gran victoria. Y luego Demetrius Clark dijo: encontrar React Query me ha ayudado a mantener un flujo de trabajo extremadamente productivo dentro de React. Con consultas y mutaciones, mis componentes expresan claramente la intención, y finalmente puedo ajustar la interfaz de usuario al flujo que mis usuarios esperan debido a las potentes estrategias de almacenamiento en caché. React Query es ahora mi gestor de estado de servidor preferido.

11. Conclusion and Invitation

Short description:

Eche un vistazo a su estado global y vea cuánto es estado del servidor y cuánto es estado del cliente. Al utilizar React Query para el estado del servidor, tendrá menos estado del cliente y una mejor experiencia de usuario. Síganme en las redes sociales y echen un vistazo a mis otros proyectos y startup, Nozzle.io. Gracias.

Así que volviendo al punto de partida, me gustaría dejarles a todos una invitación para que revisen su estado global de las aplicaciones y tomen nota de cuánto de él es estado del servidor y cuánto es estado del cliente. Creo que se sorprenderán al ver cuánto de él está realmente fuera del control de su aplicación y que al optar por manejar su estado del servidor con una herramienta como React Query, se sorprenderán nuevamente al ver cuánto estado del cliente les queda y cuánto mejorará la experiencia del usuario de su aplicación.

Así que gracias por escuchar y asegúrense de seguirme en Twitter, YouTube y GitHub. Y no olviden de revisar todos mis otros proyectos de código abierto y especialmente mi startup, Nozzle.io. Gracias.

QnA

React Query y Comunicación con el Servidor

Short description:

Estoy ansioso por probar React Query en mi propio proyecto. React Query puede admitir GraphQL con cualquier cliente GraphQL simple. Hay algo más genérico que Apollo para la comunicación con el servidor. Siempre y cuando sea transaccional y use promesas, funcionará. Para el estado restante del cliente, personalmente uso Context y useReducer para una gestión fácil.

Tengo que decir, Tanner, eso fue impresionante. Muchas gracias por esta gran charla. En realidad, estoy ansioso por probar React Query en mi propio proyecto. También creo que no cobras por hora, ¿verdad? Claro, seguro. No deberías hacer estas cosas si cobras por hora. Vamos, nos estás matando. Nos estás matando.

Quiero pasar directamente a las preguntas de la audiencia. Tenemos algunas y voy a empezar con la primera. ¿React Query también admite GraphQL utilizando Apollo Client? Así que React Query puede admitir GraphQL, pero no lo hace a través de Apollo. Si quieres usar un cliente GraphQL simple para obtener datos, realmente puedes usar cualquier cosa que desees para obtener tus datos siempre y cuando devuelva una promesa y tus datos. De hecho, tengo muchas personas que están utilizando solo un cliente GraphQL simple y React Query juntos y dicen que les encanta. Así que hay muchas cosas increíbles que pueden suceder allí. Genial, suena bien.

La siguiente pregunta es algo similar. ¿Hay algo como Apollo, pero para formas más genéricas de comunicarse con el servidor que no sea GraphQL? Sí, esa es una buena manera de decirlo. Es más genérico. No está construido específicamente para GraphQL o realmente cualquier tipo de capa de datos específica o protocolo. Siempre y cuando sea basado en transacciones y use promesas, funcionará. Solo quieres promesas. Sí, no quiero promesas vacías. Necesito tus promesas. De acuerdo, genial. Y luego tenemos otra pregunta de Ali. Él pregunta, para el poco estado restante del cliente, ¿usarías personalmente Redux o Context o cuál es tu forma preferida de hacer esto? Sí, en realidad, me quedó tan poco estado después de mover todo a React Query que terminé moviéndolo a algún Context. Uso un useReducer y uno o dos componentes de nivel base que proporcionan ese estado a través de Context al resto de mi aplicación. Y sinceramente, no podría estar más feliz. Queda tan poco estado que es muy fácil de gestionar por tu cuenta. Mm-hmm. De acuerdo.

React Query vs SWR

Short description:

React Query y SWR logran cosas similares pero tienen APIs diferentes. React Query ofrece más flexibilidad en el almacenamiento en caché de consultas por claves y proporciona el gancho useMutation para manejar efectos secundarios en las mutaciones. SWR carece de este concepto. Estas diferencias hacen que prefiera React Query.

Oh, y además, esa fue una buena pregunta para responder también sobre Redux. Tengo muchas personas que han cambiado a usar React Query para obtener sus datos y aún usan Redux para gestionar el estado real de su aplicación. Así que funcionan bien juntos. Pero no pueden vivir juntos en armonía. Mm-hmm.

De acuerdo. Pregunta de, bueno, Mai, no sé cuál es el nombre completo. Recientemente descubrí el sitio SWR y se ve genial. Es la primera vez que veo React Query en acción y también se ve realmente genial. Parecen lograr cosas similares. Si sabes, ¿podrías proporcionar algunas comparaciones y opiniones sobre los casos de uso que pueden ser adecuados para uno u otro? ¿O son prácticamente comparables? Son muy similares en términos de lo que intentan lograr. Las APIs son diferentes simplemente porque no fueron desarrolladas en conjunto. Cada uno tiene sus propias ideas sobre el diseño de APIs. Y en realidad tengo una lista de las diferencias muy pequeñas y algunas diferencias realmente importantes en la documentación de React Query. Hay un desplegable que dice cómo es esto diferente de Zyte. Y puedes ir y ver algunas de las cosas que son diferentes allí.

Una de las principales diferencias que creo es cómo se almacenan en caché las consultas por claves. La estructura de clave para React Query es un poco diferente y en mi opinión un poco más flexible para que puedas seleccionar qué consultas deseas volver a buscar, entre otras cosas. Y también el concepto completo detrás de useMutation creo que es un gancho realmente útil, especialmente cuando comienzas a hacer cosas como actualizaciones optimistas y deseas manejar declarativamente los efectos secundarios de tus mutaciones. Y eso es algo que no existe realmente en SWR en este momento. Así que esa es una de las principales razones por las que me gusta React Query. Bueno, eres parcial, diría yo. Sí, estoy extremadamente sesgado. Muy bien, Tanner, eso es todo el tiempo que tenemos para preguntas en este momento. Si tienes alguna pregunta más para Tanner, puedes ir a la sala de Zoom. Tanner, muchas gracias.

Check out more articles and videos

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

Vue.js London Live 2021Vue.js London Live 2021
34 min
Everything Beyond State Management in Stores with Pinia
Top Content
When we think about Vuex, Pinia, or stores in general we often think about state management and the Flux patterns but not only do stores not always follow the Flux pattern, there is so much more about stores that make them worth using! Plugins, Devtools, server-side rendering, TypeScript integrations... Let's dive into everything beyond state management with Pinia with practical examples about plugins and Devtools to get the most out of your stores.
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 Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
Jotai is a state management library. We have been developing it primarily for React, but it's conceptually not tied to React. It this talk, we will see how Jotai atoms work and learn about the mental model we should have. Atoms are framework-agnostic abstraction to represent states, and they are basically just functions. Understanding the atom abstraction will help designing and implementing states in your applications with Jotai
React Advanced Conference 2023React Advanced Conference 2023
28 min
A Practical Guide for Migrating to Server Components
Server Components are the hot new thing, but so far much of the discourse around them has been abstract. Let's change that. This talk will focus on the practical side of things, providing a roadmap to navigate the migration journey. Starting from an app using the older Next.js pages router and React Query, we’ll break this journey down into a set of actionable, incremental steps, stopping only when we have something shippable that’s clearly superior to what we began with. We’ll also discuss next steps and strategies for gradually embracing more aspects of this transformative paradigm.
JSNation 2022JSNation 2022
27 min
Announcing Starbeam: Universal Reactivity
Starbeam is a library for building reactive data systems that integrate natively with UI frameworks such as React, Vue, Svelte or Ember. In this talk, Yehuda will announce Starbeam. He will cover the motivation for the library, and then get into the details of how Starbeam reactivity works, and most importantly, how you can use it to build reactive libraries today that will work natively in any UI framework. If you're really adventurous, he will also talk about how you could use Starbeam in an existing app using your framework of choice and talk about the benefits of using Starbeam as the state management system in your application.
React Advanced Conference 2021React Advanced Conference 2021
19 min
React Query and Auth: Who is Responsible for What?
Top Content
React Query manages server state on the client, and auth manages user sign in/sign up/sign out. Where do these two overlap, and how do you separate concerns? This talk proposes a data flow with custom hooks for both auth and React Query to manage authentication status and user profile updates.

Workshops on related topic

React Summit 2020React Summit 2020
96 min
Rethinking Server State with React Query
Top Content
Featured Workshop
The distinction between server state and client state in our applications might be a new concept for some, but it is very important to understand when delivering a top-notch user experience. Server state comes with unique problems that often sneak into our applications surprise like:
- Sharing Data across apps- Caching & Persistence- Deduping Requests- Background Updates- Managing “Stale” Data- Pagination & Incremental fetching- Memory & Garbage Collection- Optimistic Updates
Traditional “Global State” managers pretend these challenges don’t exist and this ultimately results in developers building their own on-the-fly attempts to mitigate them.
In this workshop, we will build an application that exposes these issues, allows us to understand them better, and finally turn them from challenges into features using a library designed for managing server-state called React Query.
By the end of the workshop, you will have a better understanding of server state, client state, syncing asynchronous data (mouthful, I know), and React Query.
React Summit Remote Edition 2021React Summit Remote Edition 2021
71 min
State Management in React with Context and Hooks
WorkshopFree
A lot has changed in the world of state management in React the last few years. Where Redux used to be the main library for this, the introduction of the React Context and Hook APIs has shaken things up. No longer do you need external libraries to handle both component and global state in your applications. In this workshop you'll learn the different approaches to state management in the post-Redux era of React, all based on Hooks! And as a bonus, we'll explore two upcoming state management libraries in the React ecosystem.