Utiliser l’Optimistic UI avec React et Apollo GraphQL

Améliorez l’expérience utilisateur et la réactivité de vos applications React avec un peu d’optimisme !

Amichaud Romain
4 min readDec 16, 2020

Objectifs

  • Découvrir le principe de l’optimistic UI
  • L’utiliser avec React et GraphQL pour augmenter l’expérience utilisateur

Contexte

Le temps de réponse entre le backend et le frontend est un des facteurs limitants l’expérience utilisateur. C’est encore plus vrai lorsque l’application ou le site web est destiné aux mobiles qui peuvent avoir une connexion dégradée.

Dès qu’un utilisateur effectue une action d’envoi de données au serveur, ce qu’on appelle une mutation, l’application cliente attend le retour du serveur pour mettre à jour l’interface. Si le temps de réponse du serveur est important, l’expérience utilisateur est mauvaise.

Image de l’auteur

Un peu de théorie

L’application gère une liste de personnages, on souhaite pouvoir ajouter des personnages. Les personnages possède un ID unique, et un Username. Le réseau est très lent.

L’utilisateur veut ajouter un personnage, il doit pour cela saisir son Username et cliquer sur un bouton d’enregistrement. Une mutation est envoyé au serveur qui va créer le personnage, générer son ID et renvoyer une liste de personnages à jour.

Voici un schema des actions, lorsque tout se passe bien :

Image de l’auteur

Il pourrait éventuellement y avoir un souci côté serveur, et la création du nouveau personnage peut ne pas se dérouler comme prévu. Dans ce cas, le schéma pourrait ressembler à cela :

Image de l’auteur

L’optimistic UI est simplement le fait de se placer dans le cas ou tout se déroule comme prévu : le client ignore ce qui se passe côté serveur dans un premier temps, il part du principe que tout va bien se passer. Dans un second temps il récupère les informations du serveur, met à jour les propriétés qui ont été générés par le serveur (ici l’ID), et en cas d’erreur il revient à l’état initial.

Image de l’auteur

Pour l’utilisateur, son action est ressentie comme étant instantanée.

Lancement du projet

Pour mettre en pratique notre exemple, il nous faut une application cliente (React), un serveur (Node.js), les deux reliés par une API (GraphQL). Côté client il faudra une gestion du cache ou de l’état (state), Apollo GraphQL le fait parfaitement.

On utilise create-react-app pour bootstraper l’application cliente avec une configuration de base.

Le serveur est un serveur Apollo Graphql classique, avec un middleware express qui va simuler un temps de réponse de 1.5 secondes :

L’application cliente

Notre component React affiche une liste de personnages, on récupère la liste via une requête GraphQL. On passe ensuite la liste au compoonent qui se chargera de l’afficher.

Le component principal affiche la liste et un champ qui permet de saisir le nom du nouveau personnage :

On ajoute la mutation GraphQL grâce au hook useMutation fourni par Apollo :

L’application est fonctionnelle et permet d’ajouter un personnage et de récupérer la liste à jour provenant du serveur. L’opération de refetch de la liste prend du temps et laisse une sensation désagréable à l’utilisateur !

Soyons optimiste !

Pour ajouter de l’optimistic UI à notre application, il nous suffit de changer la stratégie de refetch des données lors de la mutation. Dans la mutation précédente, une query était passée en paramètre via la propriété “refetchQueries”, qui indiquait à GraphQL de ré-exécuter cette query après la mutation et mettre à jour le cache.

Pour utiliser l’optimistic UI d’Apollo, on a accès à deux propriétés : “optimisticResponse” et “update”.

La première propriété, “optimisticResponse” gère l’entité que l’on créé, ici le personnage, la propriété “update” définit comment mettre à jour notre cache local avec cette nouvelle entité. Cette mise à jour s’effectuera sans que l’utilisateur le perçoive, dès réception de la réponse du serveur.

Voici les deux components utilisés l’un avec Optimistic UI, l’autre sans :

Vous pouvez retrouver toutes les sources ici.

Originally published at https://romainamichaud.com.

--

--