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 .
- Requête
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.
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 fonctionfetchMore
fournie avec le crochetuseQuery
.
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.
npm install
. npm run app
pour démarrer l'application. 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:
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:
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, commeAxios
etwindow.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 esthttps: // 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 liencache
. - Enfin, nous exportez le client
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 letype
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 hookuseQuery
qui a été initialement importé de@ apollo / react-hooks
. Ensuite, nous lui passons une chaîne de requête GraphQL, qui estGET_PETS
dans notre cas.
- Comme nous effectuons une opération
- 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'inclureasync-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 composantLoader
pendant le chargement de notre application. Par défaut, le chargement estfaux
. -
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 accessoirespets
avecdata.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.
Si tout s'est bien passé, vous devriez voir ceci:
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: