Articles
Aug 21, 2024

Optimistic update avec React Query

Cet article explique comment implémenter des mises à jour optimistes avec @tanstack/react-query dans une application de liste de tâches. Découvrez la configuration, la récupération des tâches et les mutations optimistes, avec des exemples de code détaillés.

Optimistic update avec React Query

Introduction

Les mises à jour optimistes sont une technique permettant d'améliorer l'expérience utilisateur dans les applications web en devançant les réponses du serveur. Plutôt que d'attendre la confirmation du serveur pour mettre à jour l'interface utilisateur, les mises à jour optimistes permettent de refléter immédiatement les changements présumés. Si le serveur confirme la modification, tout va bien. Cependant, si le serveur rejette la demande, l'interface utilisateur revient à l'état précédent.

Dans cet article, nous verrons comment implémenter des mises à jour optimistes en utilisant @tanstack/react-query, une bibliothèque populaire de gestion des requêtes en React.

Prérequis

Assurez-vous d'avoir une application React configurée avec @tanstack/react-query. Si ce n'est pas le cas, vous pouvez l'installer en utilisant npm ou yarn :

npm install @tanstack/react-query
# ou
yarn add @tanstack/react-query

Exemple de Code

Nous allons examiner l'exemple d'application d'une liste de tâches (To-Do List) pour illustrer les mises à jour optimistes.

Configuration de base avec React Query

Commençons par configurer React Query dans notre application :

import React from 'react';
import ReactDOM from 'react-dom';
import {
  QueryClient,
  QueryClientProvider
} from '@tanstack/react-query';
import App from './App';

const queryClient = new QueryClient();

ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById('root')
);

Implémentation d'une Liste de Tâches

Ensuite, nous allons implémenter une liste de tâches avec des fonctionnalités de mise à jour optimiste.

Fetcher pour récupérer les tâches

import axios from 'axios';

const fetchTodos = async () => {
  const { data } = await axios.get('/api/todos');
  return data;
};

Composant Liste de Tâches

import React from 'react';
import {
  useQuery,
  useMutation,
  useQueryClient
} from '@tanstack/react-query';
import axios from 'axios';

const Todos = () => {
  const queryClient = useQueryClient();

  const { data: todos, isLoading } = useQuery(['todos'], fetchTodos);

  const updateTodo = useMutation(
    (updatedTodo) => axios.put(`/api/todos/${updatedTodo.id}`, updatedTodo),
    {
      onMutate: async (updatedTodo) => {
        await queryClient.cancelQueries(['todos']);
        
        const previousTodos = queryClient.getQueryData(['todos']);

        queryClient.setQueryData(['todos'], (old) =>
          old.map((todo) =>
            todo.id === updatedTodo.id ? { ...todo, ...updatedTodo } : todo
          )
        );
        
        return { previousTodos };
      },
      onError: (err, updatedTodo, context) => {
        queryClient.setQueryData(['todos'], context.previousTodos);
      },
      onSettled: () => {
        queryClient.invalidateQueries(['todos']);
      },
    }
  );

  if (isLoading) return <div>Loading...</div>;

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.text}
          <button onClick={() => updateTodo.mutate({ ...todo, completed: !todo.completed })}>
            {todo.completed ? 'Undo' : 'Complete'}
          </button>
        </li>
      ))}
    </ul>
  );
};

export default Todos;

Explication

  1. Récupération des Données: Nous utilisons useQuery pour récupérer la liste des tâches avec la clé de requête ['todos'].
  2. Mutation: La fonction de mise à jour utilise useMutation pour mettre à jour une tâche.
  3. Mise à Jour Optimiste:
    • onMutate: Avant que la mutation ne démarre, nous annulons les requêtes en cours pour ['todos'], sauvegardons l'état précédent, puis mettons à jour la tâche de manière optimiste.
    • onError: En cas d'erreur, nous rétablissons l'état précédent à l'aide des données sauvegardées.
    • onSettled: Qu'il y ait une erreur ou non, nous invalidons les requêtes ['todos'] pour synchroniser l'interface utilisateur avec les données du serveur.

Les mises à jour optimistes améliorent significativement l'expérience utilisateur en rendant l'application plus réactive et en réduisant les temps de latence perçus.

Conclusion

N'hésitez pas à adapter ces exemples à vos propres besoins et à explorer plus en profondeur les fonctionnalités offertes par React Query.