'Optimistic Updates' con Tanstack Query: Mejora la Experiencia del Usuario

Descubre el poder de las actualizaciones optimistas de la interfaz de usuario con Tanstack Query. Aprende cómo esta poderosa biblioteca mejora la experiencia del usuario al proporcionar interacciones de IU dinámicas, manejando sin problemas las actualizaciones asincrónicas de datos.

En este artículo aprenderás:

  1. ¿Qué son los Optimistic Updates?
  2. Beneficios de los Optimistic Updates
  3. ¿Cómo implementarlo con Tanstack Query?

¿Qué son los Optimistic Updates?

Los Optimistic Updates son una técnica que permite actualizar de manera instantánea la interfaz de usuario (UI) de una aplicación antes de que la respuesta del servidor llegue realmente. En lugar de esperar a que el servidor confirme una operación y luego actualizar la UI, se actualiza la UI de manera optimista inmediatamente después de que el usuario realiza una acción.

Por ejemplo, en una aplicación de redes sociales, cuando un usuario da "Me gusta" a una publicación, en lugar de esperar a que el servidor responda con la confirmación del "Me gusta", la interfaz de usuario se actualiza instantáneamente mostrando el nuevo recuento de "Me gusta". Esto da la ilusión de una respuesta rápida y mejora la experiencia del usuario al evitar retrasos perceptibles.

Beneficios de los Optimistic Updates

  1. Mejora la velocidad percibida: Al actualizar la interfaz de usuario de manera instantánea, los Optimistic Updates brindan una sensación de velocidad y respuesta rápida en la aplicación. Los usuarios no tienen que esperar a que se complete la comunicación con el servidor para ver los cambios reflejados.

  2. Experiencia de usuario sin interrupciones: Al evitar retrasos perceptibles, los Optimistic Updates evitan que los usuarios experimenten interrupciones en su flujo de trabajo. Pueden continuar interactuando con la aplicación sin pausas innecesarias.

¿Cómo implementarlo con Tanstack Query?

Si no estás familiarizado con Tanstack Query, te recomiendo leer mi artículo Optimiza la gestión de datos en tu aplicación Vue con 'Queries y Mutations' para que puedas entender mejor los conceptos que se explican a continuación.

Si ya estás familiarizado con Tanstack Query pero no entiendes a fondo cómo funcionan las mutaciones, te recomiendo leer mi artículo Ejecutando código después una mutación exitosa en React y Vue para que puedas entender mejor los conceptos que se explican a continuación.

onMutate

El callback onMutate se ejecuta antes de que se envíe la mutación al servidor. Este callback recibe como parámetro el valor que se le pasa a la mutación. Esto nos permite tener acceso a los datos que se van a enviar al servidor antes de que se envíen y de esta manera replicar los cambios que el servidor haría si la llamada a la API fuera exitosa. De esta manera podemos actualizar optimistamente la interfaz de usuario antes de que la mutación se envíe al servidor y así mejorar la experiencia del usuario para que no tenga que esperar a que la mutación se complete para ver los cambios reflejados.

queryClient.setQueryData( queryKey, updater )

El método setQueryData nos permite actualizar los datos de una query de manera manual. Recibe como parámetro el queryKey de la query que queremos actualizar y un updater que es una función que recibe como parámetro los datos actuales de la query y devuelve los nuevos datos que queremos asignarle a la query.

queryClient.cancelQueries( queryKey )

El método cancelQueries nos permite cancelar todas las queries que estén en curso. Recibe como parámetro el queryKey de la query que queremos cancelar. Es una petición asíncrona, por lo que podemos utilizar await para esperar a que se complete la petición antes de continuar con el código.

queryClient.invalidateQueries( queryKey )

El método invalidateQueries nos permite invalidar una query para que se vuelva a ejecutar y obtener los datos más recientes. Recibe como parámetro el queryKey de la query que queremos invalidar.

Implementación

const queryClient = useQueryClient();

const { mutate } = useMutation(updateTodoFunction, {
  // Cuando se llama a "mutate":
  onMutate: async (newTodo) => {
    // Cancela cualquier solicitud de recuperación en curso (para que no sobrescriba nuestra actualización optimista)
    await queryClient.cancelQueries({ queryKey: ["todos"] });

    // Captura el valor anterior
    const previousTodos = queryClient.getQueryData(["todos"]);

    // Actualiza optimistamente al nuevo valor
    queryClient.setQueryData(["todos"], (old) => [...old, newTodo]);

    // Devuelve un objeto de contexto con el valor capturado
    return { previousTodos };
  },
  // Si la mutación falla, utiliza el contexto devuelto por onMutate para deshacer los cambios
  onError: (err, newTodo, context) => {
    queryClient.setQueryData(["todos"], context.previousTodos);
  },
  // Siempre vuelve a obtener los datos después de un error o éxito:
  onSettled: () => {
    queryClient.invalidateQueries({ queryKey: ["todos"] });
  },
});

Ayúdame a mejorar este artículo

¿Quisieras complementar este artículo o encontraste algún error?¡Excelente! Envíame un correo.

  • seb@sebastianfdz.com