Fermer

juillet 29, 2020

Comprendre GraphQl côté client avec ApolloClient dans React Apps


À propos de l'auteur

Blessing Krofegha est un ingénieur logiciel basé à Lagos au Nigeria, avec un désir ardent de contribuer à rendre le Web génial pour tous, en écrivant et en construisant…
En savoir plus sur
Bénédiction

Avez-vous déjà essayé d'interagir avec un serveur GraphQL dans une application côté client et avez-vous eu envie d'abandonner avant même d'aller quelque part? Avez-vous déjà refusé une invitation à rejoindre une base de code qui nécessite de travailler avec l'API GraphQL parce que vous n'en aviez aucune idée? Vous êtes-vous déjà senti comme le seul ingénieur front-end à ne pas avoir appris à utiliser les API GraphQL? Si vous avez répondu oui à l'une de ces questions, ce didacticiel est fait pour vous. Nous allons examiner de plus près quelques principes de base de GraphQL et Apollo Client, ainsi que la façon de travailler avec les deux. À la fin, nous aurons créé une application pour animalerie qui utilise Apollo Client. Ensuite, vous pouvez continuer à créer votre prochain projet.

Selon State of JavaScript 2019 38,7% des développeurs aimeraient utiliser GraphQL, tandis que 50,8% des développeurs aimeraient apprendre GraphQL. [19659005] En tant que langage de requête, GraphQL simplifie le flux de travail de construction d'une application client. Il supprime la complexité de la gestion des points de terminaison d'API dans les applications côté client, car il expose un seul point de terminaison HTTP pour récupérer les données requises. Par conséquent, il élimine la surextraction et la sous-extraction des données comme dans le cas de REST.

Mais GraphQL est juste un langage de requête. Afin de l'utiliser facilement, nous avons besoin d'une plate-forme qui fait le gros du travail à notre place. Une de ces plates-formes est Apollo.

La plate-forme Apollo est une implémentation de GraphQL qui transfère des données entre le cloud (le serveur) vers l'interface utilisateur de votre application. Lorsque vous utilisez Apollo Client, toute la logique de récupération des données, de suivi, de chargement et de mise à jour de l'interface utilisateur est encapsulée par le hook useQuery (comme dans le cas de React). Par conséquent, la récupération des données est déclarative. Il a également une mise en cache sans configuration. En configurant simplement Apollo Client dans votre application, vous obtenez un cache intelligent prêt à l'emploi, sans configuration supplémentaire requise.

Apollo Client est également interopérable avec d'autres frameworks, tels que Angular, Vue.js et React. [19659005] Note : Ce didacticiel profitera à ceux qui ont travaillé avec RESTful ou d'autres formes d'API dans le passé côté client et qui veulent voir si GraphQL vaut la peine d'être essayé. Cela signifie que vous devriez avoir déjà travaillé avec une API; ce n'est qu'alors que vous pourrez comprendre à quel point GraphQL pourrait vous être bénéfique. Bien que nous couvrions quelques bases de GraphQL et d'Apollo Client, une bonne connaissance de JavaScript et React Hooks sera utile.

Notions de base de GraphQL

Cet article n'est pas une introduction complète à GraphQL, mais nous définirons quelques conventions avant de continuer.

Qu'est-ce que GraphQL?

GraphQL est une spécification qui décrit un langage de requête déclaratif que vos clients peuvent utiliser pour demander à une API données qu'ils veulent. Ceci est réalisé en créant un schéma de type fort pour votre API, avec une flexibilité ultime. Il garantit également que l'API résout les données et que les requêtes des clients sont validées par rapport à un schéma. Cette définition signifie que GraphQL contient des spécifications qui en font un langage de requête déclaratif, avec une API typée statiquement (construite autour de Typescript) et permettant au client d'exploiter ces systèmes de types pour demander à l'API les données exactes qu'il souhaite

Donc, si nous avons créé des types avec des champs, alors, du côté client, nous pourrions dire: «Donnez-nous ces données avec ces champs exacts». Ensuite, l'API répondra avec cette forme exacte, comme si nous utilisions un système de type dans un langage fortement typé. Vous pouvez en apprendre plus dans mon article Typescript .

Examinons quelques conventions de GraphQl qui nous aideront à continuer.

Les bases

  • Opérations
    Dans GraphQL, chaque action effectuée est appelée une opération. Il existe quelques opérations, à savoir:
    • Requête
      Cette opération concerne la récupération des données du serveur. Vous pouvez également appeler cela une extraction en lecture seule.
    • Mutation
      Cette opération implique la création, la mise à jour et la suppression de données d'un serveur. Elle est communément appelée opération CUD (création, mise à jour et suppression).
    • Abonnements
      Cette opération dans GraphQL implique l'envoi de données d'un serveur à ses clients lorsque des événements spécifiques se produisent. Ils sont généralement implémentés avec WebSockets .

Dans cet article, nous ne traiterons que des opérations de requête et de mutation.

  • Opération noms
    Il y a noms uniques pour vos opérations de requête et de mutation côté client.
  • Variables et arguments
    Les opérations peuvent définir des arguments, tout comme une fonction dans la plupart des langages de programmation. Ces variables peuvent ensuite être transmises aux appels de requête ou de mutation à l'intérieur de l'opération en tant qu'arguments. Les variables doivent être fournies lors de l'exécution pendant l'exécution d'une opération à partir de votre client.
  • Aliasing
    Il s'agit d'une convention dans GraphQL côté client qui consiste à renommer des noms de champs verbeux ou vagues avec des noms de champs simples et lisibles pour le UI. Le crénelage est nécessaire dans les cas d’utilisation où vous ne voulez pas avoir de noms de champ en conflit.
 Conventions de base de GraphQL
Conventions de base de GraphQL. ( Grand aperçu )

Qu'est-ce que GraphQL côté client?

Lorsqu'un ingénieur frontal construit des composants d'interface utilisateur en utilisant n'importe quel framework, comme Vue.js ou (dans notre cas) React, ces composants sont modélisés et conçus à partir d'un certain modèle sur le client pour s'adapter aux données qui seront extraites du serveur.

L'un des problèmes les plus courants avec les API RESTful est la surextraction et la sous-extraction. Cela se produit parce que la seule façon pour un client de télécharger des données est de toucher les points de terminaison qui renvoient des structures de données fixes. La surextraction dans ce contexte signifie qu'un client télécharge plus d'informations que ce qui est requis par l'application.

Dans GraphQL, par contre, vous envoyez simplement une seule requête au serveur GraphQL qui inclut le données requises. Le serveur répondrait alors avec un objet JSON contenant les données exactes que vous avez demandées, donc pas de surextraction. Sebastian Eschweiler explique les différences entre les API RESTful et GraphQL .

GraphQL côté client est une infrastructure côté client qui s'interface avec les données d'un serveur GraphQL pour exécuter les fonctions suivantes:

  • Il gère les données en envoyant des requêtes et en faisant muter les données sans que vous ayez à construire vous-même des requêtes HTTP. Vous pouvez passer moins de temps à analyser les données et plus de temps à créer l'application réelle.
  • Il gère la complexité d'un cache pour vous. Ainsi, vous pouvez stocker et récupérer les données récupérées sur le serveur, sans aucune interférence de tiers, et éviter facilement de récupérer les ressources en double. Ainsi, il identifie quand deux ressources sont identiques, ce qui est idéal pour une application complexe.
  • Il maintient votre interface utilisateur cohérente avec l'interface utilisateur optimiste, une convention qui simule les résultats d'une mutation (c'est-à-dire les données créées) et met à jour l'interface utilisateur avant même de recevoir une réponse du serveur. Une fois la réponse reçue du serveur, le résultat optimiste est jeté et remplacé par le résultat réel.

Pour plus d'informations sur GraphQL côté client, consacrez une heure avec le cocréateur de GraphQL et d'autres gens sympas sur GraphQL Radio .

Qu'est-ce qu'Apollo Client?

Apollo Client est un client GraphQL interopérable ultra-flexible et géré par la communauté pour JavaScript et les plates-formes natives. Ses fonctionnalités impressionnantes incluent un outil robuste de gestion d'état ( Apollo Link ), un système de mise en cache sans configuration une approche déclarative pour récupérer des données, facile à utiliser -implement pagination et Optimistic UI pour votre application côté client.

Apollo Client stocke non seulement l'état des données extraites du serveur, mais également l'état qui il a créé localement sur votre client; par conséquent, il gère l'état des données API et des données locales.

Il est également important de noter que vous pouvez utiliser Apollo Client avec d'autres outils de gestion d'état, comme Redux, sans conflit. De plus, il est possible de migrer la gestion de l’état de, par exemple, Redux vers Apollo Client (ce qui dépasse le cadre de cet article). En fin de compte, l'objectif principal d'Apollo Client est de permettre aux ingénieurs d'interroger les données dans une API de manière transparente.

Fonctionnalités d'Apollo Client

Apollo Client a convaincu de nombreux ingénieurs et entreprises en raison de ses fonctionnalités extrêmement utiles qui rendent la construction moderne applications robustes un jeu d'enfant. Les fonctionnalités suivantes sont intégrées:

  • Caching
    Apollo Client prend en charge la mise en cache à la volée.
  • Optimistic UI
    Apollo Client prend en charge l'interface Optimistic UI. Il s'agit d'afficher temporairement l'état final d'une opération (mutation) pendant que l'opération est en cours. Une fois l'opération terminée, les données réelles remplacent les données optimistes.
  • Pagination
    Apollo Client a une fonctionnalité intégrée qui facilite la mise en œuvre de la pagination dans votre application. Il s'occupe de la plupart des maux de tête techniques liés à la récupération d'une liste de données, soit sous forme de correctifs, soit immédiatement, à l'aide de la fonction fetchMore fournie avec le crochet useQuery .

Dans cet article, nous examinerons une sélection de ces caractéristiques.

Assez de théorie. Serrez votre ceinture de sécurité et prenez une tasse de café pour accompagner vos crêpes, car nous nous salissons les mains.

Construire notre application Web

Ce projet est inspiré de Scott Moss.

Nous allons créer une application Web simple pour animalerie, dont les fonctionnalités incluent:

  • récupérer nos animaux de compagnie du côté serveur;
  • créer un animal de compagnie (ce qui implique la création du nom, du type d'animal et de l'image);
  • ] en utilisant l'interface optimiste;
  • en utilisant la pagination pour segmenter nos données.

Pour commencer, clonez le référentiel, en vous assurant que la branche starter est bien celle que vous avez clonée.

Mise en route [19659073] Installez l'extension Apollo Client Developer Tools pour Chrome.
  • À l'aide de l'interface de ligne de commande (CLI), accédez au répertoire du référentiel cloné et exécutez la commande pour obtenir toutes les dépendances: npm install .
  • Exécutez la commande npm run app pour démarrer l'application.
  • Pendant que sti ll dans le dossier racine, exécutez la commande npm run server . Cela démarrera notre serveur principal pour nous, que nous utiliserons au fur et à mesure.
  • L'application devrait s'ouvrir dans un port configuré. Le mien est http: // localhost: 1234 / ; le vôtre est probablement autre chose.

    Si tout a bien fonctionné, votre application devrait ressembler à ceci:

     Interface utilisateur de branche de démarrage clonée
    Interface utilisateur de branche de démarrage clonée. ( Grand aperçu )

    Vous remarquerez que nous n'avons aucun animal à afficher. C'est parce que nous n'avons pas encore créé de telles fonctionnalités.

    Si vous avez correctement installé Apollo Client Developer Tools ouvrez les outils de développement et cliquez sur l'icône de la barre d'état. Vous verrez "Apollo" et quelque chose comme ceci:

     Apollo Client Developer Tools
    Apollo Client Developer Tools. ( Grand aperçu )

    Comme les outils de développement Redux et React, nous utiliserons Apollo Client Developer Tools pour écrire et tester nos requêtes et mutations. L'extension est fournie avec le GraphQL Playground .

    Fetching Pets

    Ajoutons la fonctionnalité qui récupère les animaux de compagnie. Accédez à client / src / client.js . Nous allons écrire Apollo Client, le lier à une API, l'exporter comme client par défaut et écrire une nouvelle requête.

    Copiez le code suivant et collez-le dans client.js :

     ] importer {ApolloClient} depuis 'apollo-client'
    importer {InMemoryCache} depuis 'apollo-cache-inmemory'
    importer {HttpLink} depuis 'apollo-link-http'
    
    lien const = nouveau HttpLink ({uri: 'https: // localhost: 4000 /'})
    cache const = nouveau InMemoryCache ()
    client const = new ApolloClient ({
      lien,
      cache
    })
    Exporter le client par défaut 

    Voici une explication de ce qui se passe ci-dessus:

    • ApolloClient
      Ce sera la fonction qui encapsulera notre application et, par conséquent, s'interface avec HTTP, met en cache les données et met à jour le UI.
    • InMemoryCache
      Ceci est le magasin de données normalisé dans Apollo Client qui aide à manipuler le cache dans notre application.
    • HttpLink
      Il s'agit d'une interface réseau standard pour modifier le contrôler le flux des requêtes GraphQL et récupérer les résultats GraphQL. Il agit comme un middleware, récupérant les résultats du serveur GraphQL à chaque fois que le lien est déclenché. De plus, c'est un bon substitut à d'autres options, comme Axios et window.fetch .
    • Nous déclarons une variable de lien qui est affectée à une instance de HttpLink ]. Il faut une propriété uri et une valeur à notre serveur, qui est https: // localhost: 4000 / .
    • Ensuite est une variable de cache qui contient la nouvelle instance de InMemoryCache .
    • La variable client prend également une instance de ApolloClient et encapsule le lien et cache .
    • Enfin, nous exportez le client afin que nous puissions l'utiliser dans toute l'application.

    Avant de voir cela en action, nous devons nous assurer que toute notre application est exposée à Apollo et que notre application peut recevoir des données extraites du serveur et qu'il peut muter ces données.

    Pour ce faire, passons à client / src / index.js :

     import React from 'react'
    importer ReactDOM depuis 'react-dom'
    importer {BrowserRouter} depuis 'react-router-dom'
    importer {ApolloProvider} depuis '@ apollo / react-hooks'
    importer l'application depuis './components/App'
    importer le client depuis './client'
    import './index.css'
    const Racine = () => (
      
        
          
        
      
    );
    ReactDOM.render (document.getElementById ('app'))
    if (module.hot) {
      module.hot.accept ()
    } 

    Comme vous le remarquerez dans le code en surbrillance, nous avons encapsulé le composant App dans ApolloProvider et avons passé le client comme accessoire au client ]. ApolloProvider est similaire au Context.Provider de React. Il encapsule votre application React et place le client en contexte, ce qui vous permet d'y accéder de n'importe où dans votre arborescence de composants.

    Pour récupérer nos familiers sur le serveur, nous devons écrire des requêtes qui demandent les champs exacts que nous voulons. Rendez-vous sur client / src / pages / Pets.js et copiez-collez-y le code suivant:

     import React, {useState} de 'react'
    importer gql depuis 'graphql-tag'
    import {useQuery, useMutation} depuis '@ apollo / react-hooks'
    importer PetsList depuis '../components/PetsList'
    importer NewPetModal depuis '../components/NewPetModal'
    import Loader de '../components/Loader'[19659110[/19659110.) GET_PETS = gql`
      query getPets {
        animaux domestiques {
          id
          Nom
          type
          img
        }
      }
    `; 
    
     fonction par défaut d'exportation Pets () {
      const [modal, setModal] = useState (false) 
       const {chargement, erreur, données} = useQuery (GET_PETS);
    
      if (chargement) retour ;
    
      if (error) return 

    Une erreur s'est produite!

    ;
    const onSubmit = input => { setModal (faux) } if (modal) { return setModal (false)} /> } revenir (

    Animaux

    ) }

    Avec quelques bits de code, nous pouvons récupérer les familiers du serveur.

    Qu'est-ce que gql?

    Il est important de noter que les opérations dans GraphQL sont généralement des objets JSON écrits avec graphql- balise et avec des incrustations.

    Les balises gql sont des balises littérales de modèle JavaScript qui analysent les chaînes de requête GraphQL dans GraphQL AST (arbre de syntaxe abstraite) .

    • Opérations de requête
      Pour récupérer nos familiers du serveur, nous devons effectuer une opération de requête.
      • Comme nous effectuons une opération query nous devions spécifier le type d'opération avant de la nommer.
      • Le nom de notre requête est GET_PETS . C’est une convention de dénomination de GraphQL pour utiliser camelCase pour les noms de champ.
      • Le nom de nos champs est pets . Par conséquent, nous spécifions les champs exacts dont nous avons besoin du serveur (id, nom, type, img) .
      • useQuery est un React hook qui est la base pour exécuter des requêtes dans une application Apollo. Pour effectuer une opération de requête dans notre composant React, nous appelons le hook useQuery qui a été initialement importé de @ apollo / react-hooks . Ensuite, nous lui passons une chaîne de requête GraphQL, qui est GET_PETS dans notre cas.
    • Lorsque notre composant est rendu, useQuery renvoie une réponse d'objet d'Apollo Client qui contient les propriétés de chargement, d'erreur et de données. Ainsi, ils sont déstructurés, de sorte que nous pouvons les utiliser pour rendre l'interface utilisateur.
    • useQuery est génial. Il n'est pas nécessaire d'inclure async-await . Il est déjà pris en charge en arrière-plan. Assez cool, non?
      • loading
        Cette propriété nous aide à gérer l'état de chargement de l'application. Dans notre cas, nous renvoyons un composant Loader pendant le chargement de notre application. Par défaut, le chargement est faux .
      • error
        Juste au cas où, nous utilisons cette propriété pour gérer toute erreur qui pourrait se produire.
      • data
        This contient nos données réelles du serveur.
      • Enfin, dans notre composant PetsList nous passons les accessoires pets avec data.pets comme valeur d'objet .

    À ce stade, nous avons interrogé avec succès notre serveur.

    Pour démarrer notre application, exécutons la commande suivante:

    • Démarrez l'application cliente. Exécutez la commande npm run app dans votre CLI.
    • Démarrez le serveur. Exécutez la commande npm run server dans une autre CLI.
     VScode CLI partitionnée pour démarrer à la fois le client et le serveur.
    VScode CLI partitionnée pour démarrer à la fois le client et le serveur. ( Grand aperçu )

    Si tout s'est bien passé, vous devriez voir ceci:

     Animaux interrogés depuis le serveur.
    Animaux interrogés depuis le serveur.

    Mutating Data

    Mutating ou la création de données dans Apollo Client est presque identique à l'interrogation de données, avec de très légères modifications.

    Toujours dans client / src / pages / Pets.js copions et collons le code en surbrillance: [19659109] ….

    const GET_PETS = gql`
    query getPets {
    animaux domestiques {
    id
    Nom
    type
    img
    }
    }
    `;

    const NEW_PETS = gql`
    mutation CreateAPet ($ newPet: NewPetInput!) {
    addPet (entrée: $ newPet) {
    id
    Nom
    type
    img
    }
    }
    `;

    const Pets = () => {
    const [modal, setModal] = useState (faux)
    const {chargement, erreur, données} = useQuery (GET_PETS);

    const [createPet, newPet] = useMutation (NEW_PETS);
    const onSubmit = input => {
    setModal (false)

    createPet ({
    variables: {newPet: input}
    });
    }

    if (chargement || newPet.loading) return ;

    if (error || newPet.error) return

    Une erreur s'est produite

    ;

    if (modal) {
    return setModal (false)} />
    }
    revenir (

    Animaux


    )
    }

    exporter les animaux par défaut

    Pour créer une mutation, nous prendrions les étapes suivantes:

    1. mutation

    Pour créer, mettre à jour ou supprimer, nous devons effectuer l'opération mutation . L'opération de mutation a un nom CreateAPet avec un argument. Cet argument a une variable $ newPet avec un type de NewPetInput . ! signifie que l'opération est requise; Ainsi, GraphQL n’exécutera pas l’opération à moins de passer une variable newPet dont le type est NewPetInput .

    2. addPet

    La fonction addPet qui se trouve à l'intérieur de l'opération mutation prend un argument de input et est définie sur notre Variable $ newPet . Les jeux de champs spécifiés dans notre fonction addPet doivent être égaux aux jeux de champs de notre requête. Les jeux de champs dans notre opération sont:

    3. useMutation

    Le useMutation React hook est l'API principale pour exécuter des mutations dans une application Apollo. Lorsque nous avons besoin de faire muter des données, nous appelons useMutation dans un composant React et lui passons une chaîne GraphQL (dans notre cas, NEW_PETS ).

    When our component rend useMutation il retourne un tuple (c'est-à-dire un ensemble ordonné de données constituant un enregistrement) dans un tableau qui comprend:

    • une fonction mutate que l'on peut appeler à tout moment pour exécuter le mutation;
    • un objet avec des champs qui représentent l'état actuel de l'exécution de la mutation.

    Le hook useMutation reçoit une chaîne de mutation GraphQL (qui est NEW_PETS dans notre cas ). Nous avons déstructuré le tuple, qui est la fonction ( createPet ) qui va muter les données et le champ objet ( newPets ).

    4. createPet

    Dans notre fonction onSubmit peu de temps après l'état setModal nous avons défini notre createPet . Cette fonction prend une variable avec une propriété d'objet d'une valeur définie sur {newPet: input} . L'entrée représente les différents champs d'entrée de notre formulaire (tels que le nom, le type, etc.).

    Une fois cela fait, le résultat devrait ressembler à ceci:

     Mutation sans mise à jour instantanée [19659149] Mutation sans mise à jour instantanée.</figcaption data-recalc-dims=

    Si vous observez attentivement le GIF, vous remarquerez que notre familier créé n'apparaît pas instantanément, uniquement lorsque la page est actualisée. Cependant, il a été mis à jour sur le serveur.

    La grande question est: pourquoi notre animal ne se met-il pas à jour instantanément? Découvrons-le dans la section suivante.

    Mise en cache dans Apollo Client

    La raison pour laquelle notre application ne se met pas à jour automatiquement est que nos données nouvellement créées ne correspondent pas aux données de cache d'Apollo Client. Donc, il y a un conflit quant à ce qu'il faut exactement mettre à jour à partir du cache.

    En termes simples, si nous effectuons une mutation qui met à jour ou supprime plusieurs entrées (un nœud), alors nous sommes responsables de la mise à jour de toutes les requêtes référençant ce nœud, de sorte qu'il modifie nos données mises en cache pour qu'elles correspondent aux modifications qu'une mutation apporte à nos données back-end .

    Garder le cache synchronisé

    Il existe un quelques façons de garder notre cache synchronisé chaque fois que nous effectuons une opération de mutation.

    La première consiste à récupérer les requêtes correspondantes après une mutation, en utilisant la propriété d'objet refetchQueries (la manière la plus simple).

    Remarque: Si nous devions utiliser cette méthode, elle prendrait une propriété object dans notre fonction createPet appelée refetchQueries et elle contiendrait un tableau d'objets avec une valeur de la requête: refetchQueries: [{ query: GET_PETS }].

    Car o Notre objectif dans cette section n'est pas seulement de mettre à jour nos familiers créés dans l'interface utilisateur, mais pour manipuler le cache, nous n'utiliserons pas cette méthode.

    La deuxième approche consiste à utiliser la mise à jour fonction. Dans Apollo Client, il existe une fonction d'assistance update qui permet de modifier les données du cache, afin qu'elles se synchronisent avec les modifications apportées par une mutation à nos données back-end. En utilisant cette fonction, nous pouvons lire et écrire dans le cache.

    Mise à jour du cache

    Copiez le code en surbrillance suivant et collez-le dans client / src / pages / Pets.js :

     ] ......
    const Animaux = () => {
      const [modal, setModal] = useState (faux)
      const {chargement, erreur, données} = useQuery (GET_PETS); 
       const [createPet, newPet] = useMutation (NEW_PETS, {
        update (cache, {data: {addPet}}) {
          const data = cache.readQuery ({requête: GET_PETS});
          cache.writeQuery ({
            requête: GET_PETS,
            données: {pets: [addPet, ...data.pets]},
          });
        },
        }
      ); 
       .....
    

    La fonction update reçoit deux arguments:

    • Le premier argument est le cache d'Apollo Client.
    • Le second est la réponse de mutation exacte du serveur. Nous déstructurons la propriété data et la définissons sur notre mutation ( addPet ).

    Ensuite, pour mettre à jour la fonction, nous devons vérifier quelle requête doit être mise à jour (dans notre cas, la requête GET_PETS ) et lire le cache.

    Deuxièmement, nous devons écrire dans la requête qui a été lue, afin qu'elle sache que nous sommes sur le point de mettre à jour il. Pour ce faire, nous transmettons un objet contenant une propriété d'objet query avec la valeur définie sur notre opération query ( GET_PETS ), et une donnée propriété dont la valeur est un objet pet et qui a un tableau de la mutation addPet et une copie des données de l'animal.

    Si vous avez suivi ces étapes attentivement, vous devrait voir vos animaux se mettre à jour automatiquement au fur et à mesure que vous les créez. Jetons un coup d'œil aux changements:

     Pets se met à jour instantanément
    Pets se met à jour instantanément.

    Optimistic UI

    Beaucoup de gens sont de grands fans de chargeurs et de fileuses. Il n'y a rien de mal à utiliser un chargeur; il existe des cas d'utilisation parfaits où un chargeur est la meilleure option. J'ai écrit sur loaders versus spinners et leurs meilleurs cas d'utilisation.

    Les chargeurs et les spinners jouent en effet un rôle important dans la conception UI et UX, mais l'arrivée d'Optimistic UI a volé la vedette.

    ] Qu'est-ce qu'une interface utilisateur optimiste?

    L'interface utilisateur optimiste est une convention qui simule les résultats d'une mutation (données créées) et met à jour l'interface utilisateur avant de recevoir une réponse du serveur. Une fois la réponse reçue du serveur, le résultat optimiste est rejeté et remplacé par le résultat réel.

    En fin de compte, une interface utilisateur optimiste n'est rien de plus qu'un moyen de gérer les performances perçues et d'éviter les états de chargement.

    Apollo Client a une manière très intéressante d'intégrer l'interface utilisateur optimiste. Cela nous donne un crochet simple qui nous permet d'écrire dans le cache local après la mutation. Voyons comment cela fonctionne!

    Étape 1

    Rendez-vous sur client / src / client.js et ajoutez uniquement le code en surbrillance.

     import {ApolloClient} depuis 'apollo-client '
    importer {InMemoryCache} depuis 'apollo-cache-inmemory'
    import {HttpLink} depuis 'apollo-link-http' 
     import {setContext} depuis 'apollo-link-context'
    importer {ApolloLink} depuis 'apollo-link'
    const http = new HttpLink ({uri: "http: // localhost: 4000 /"});
    retard const = setContext (
      demande =>
        nouvelle promesse ((succès, échec) => {
          setTimeout (() => {
            Succès()
          }, 800)
        })
    )
    const link = ApolloLink.from ([
      delay,
      http
    ]) 
     const cache = new InMemoryCache ()
    client const = new ApolloClient ({
      lien,
      cache
    })
    exporter le client par défaut
    

    La première étape implique ce qui suit:

    • Nous importons setContext depuis apollo-link-context . La fonction setContext prend une fonction de rappel et renvoie une promesse dont setTimeout est réglé sur 800ms afin de créer un délai lorsqu'une opération de mutation est effectuée. [19659045] La méthode ApolloLink.from garantit que l'activité réseau qui représente le lien (notre API) depuis HTTP est retardée.

    Étape 2

    La prochaine étape consiste à utiliser le hook de l'interface utilisateur optimiste. Revenez à client / src / pages / Pets.js et ajoutez uniquement le code en surbrillance ci-dessous.

     .....
    
    const Animaux = () => {
      const [modal, setModal] = useState (faux)
      const {chargement, erreur, données} = useQuery (GET_PETS);
      const [createPet, newPet] = useMutation (NEW_PETS, {
        update (cache, {data: {addPet}}) {
          const data = cache.readQuery ({requête: GET_PETS});
          cache.writeQuery ({
            requête: GET_PETS,
            données: {pets: [addPet, ...data.pets]},
          });
        },
        }
      );
      const onSubmit = entrée => {
        setModal (faux)
        createPet ({
          variables: {newPet: input}, 
       optimisticResponse: {
            __typename: 'Mutation',
            addPet: {
              __typename: 'Pet',
              id: Math.floor (Math.random () * 10000 + ''),
              nom: input.name,
              type: input.type,
              img: 'https://via.placeholder.com/200'
            }
          } 
      });
      }
      .....
    

    L'objet optimisticResponse est utilisé si nous voulons que l'interface utilisateur se mette à jour immédiatement lorsque nous créons un animal de compagnie, au lieu d'attendre la réponse du serveur.

    Les extraits de code ci-dessus incluent les éléments suivants:

    • __ typename est injecté par Apollo dans la requête pour récupérer le type des entités interrogées. Ces types sont utilisés par Apollo Client pour construire la propriété id (qui est un symbole) à des fins de mise en cache dans apollo-cache . Ainsi, __ typename est une propriété valide de la réponse à la requête.
    • La mutation est définie comme __ typename de optimisticResponse .
    • Exactement comme défini précédemment , le nom de notre mutation est addPet et le __ typename est Pet .
    • Voici les champs de notre mutation que nous voulons que la réponse optimiste mette à jour:
      • id
        Comme nous ne savons pas quel sera l'ID du serveur, nous en avons créé un en utilisant Math.floor .
      • name
        Cette valeur est définie sur input.name .
      • type
        La valeur du type est input.type .
      • img
        Now , because our server generates images for us, we used a placeholder to mimic our image from the server.

    This was indeed a long ride. If you got to the end, don’t hesitate to take a break from your chair with your cup of coffee.

    Let’s take a look at our outcome. The supporting repository for this project is on GitHub. Clone and experiment with it.

    Final Outcome of the pet shop app
    Final result of our app.

    Conclusion

    The amazing features of Apollo Client, such as the Optimistic UI and pagination, make building client-side apps a reality.

    While Apollo Client works very well with other frameworks, such as Vue.js and Angular, React developers have Apollo Client Hooks, and so they can’t help but enjoy building a great app.

    In this article, we’ve only scratched the surface. Mastering Apollo Client demands constant practice. So, go ahead and clone the repository, add pagination, and play around with the other features it offers.

    Please do share your feedback and experience in the comments section below. We can also discuss your progress on Twitter. Cheers!

    References

    Smashing Editorial(ks, ra, al, yk, il)






    Source link

    Revenir vers le haut