GraphQL avec REST & gestion de cache

GraphQL avec REST & gestion de cache


Mise en place d'Apollo client

Initialisation du projet front

Pour commencer, clonez la branche "step-2" de ce projet, mettez-vous sur le commit suivant. Nous avons besoin d'éxécuter la commande suivante pour prendre en compte les modifications du fichier docker-compose.yml :

docker-compose up -d

L'application front en React est disponible sur http://localhost:3001/.

Initialisation d'Apollo client

Afin de démarrer, nous allons ajouter de nouvelles dépendances dans l'application :

docker-compose exec front-app yarn add apollo-client apollo-cache-inmemory apollo-link apollo-link-http apollo-link-error react-apollo graphql graphql-tag --save

apollo-client, react-apollo, graphql et graphql-tag sont le minimum dont nous allons avoir besoin. Nous avons également ajouté d'autres librairies qui vont nous permettre de mettre en place la gestion des erreurs et la connexion à notre serveur Apollo.

Je vous invite à lire en détail la documentation d'Apollo sur la configuration de plusieurs links et la page sur le fonctionnement de link.

Ainsi, je vais commencer la configuration de mon client. Dans le dossier src/ je vais créer un nouveau dossier graphql/helpers qui contiendra la configuration.

Voici le code pour créer un httpLink :

// src/graphql/helpers/httpLink.js import { createHttpLink } from 'apollo-link-http'; const httpLink = createHttpLink({ uri: 'http://localhost:3000/graphql', }); export default httpLink;

Ensuite, je vais créer le fichier errorLink :

// src/graphql/helpers/errorLink.js import { onError } from 'apollo-link-error'; const errorLink = onError(({ networkError, graphQLErrors }) => { if (graphQLErrors) { graphQLErrors.forEach(({ message, locations, path }) => { console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`); }); } if (networkError) { console.log(`[Network error]: ${networkError}`); } }); export default errorLink;

Vous remarquerez que nous avons également installé apollo-cache-inmemory. En effet, ApolloClient demande d'avoir un système de cache obligatoirement lors de l'initialisation. InMemoryCache est la solution recommandée par Apollo.

Maintenant, j'ai besoin d'initialiser un client Apollo avec les links et le cache ci-dessus. Je vais faire ceci dans un fichier à part pour bien séparer mes différents besoins :

// src/graphql/helpers/client.js import { ApolloLink } from 'apollo-link'; import { ApolloClient } from 'apollo-client'; import { InMemoryCache } from 'apollo-cache-inmemory'; import errorLink from './errorLink'; import httpLink from './httpLink'; const createGraphQLClient = () => { return new ApolloClient({ link: ApolloLink.from([errorLink, httpLink]), cache: new InMemoryCache(), }); }; export default createGraphQLClient;

Enfin, passons le client Apollo à l'application :

// index.js import React from 'react'; import ReactDOM from 'react-dom'; import { ApolloProvider } from 'react-apollo'; import './index.css'; import App from './App'; import createClientGraphQL from './graphql/helpers/client'; ReactDOM.render(( <ApolloProvider client={createClientGraphQL()}> <App /> </ApolloProvider> ), document.getElementById('root'));

Récupération des données depuis le serveur

Nous sommes enfin prêts pour faire notre première query ! Je vais placer toutes les requêtes dans le dossier graphql/queries.

// graphql/queries/apod.js import gql from 'graphql-tag'; export const APOD = gql` query APOD { apod { title url date explanation type } } `;

Nous écrivons la même requête que dans le playground du serveur.

Apollo client fournit un composant Query :

import React from 'react'; import { Query } from 'react-apollo'; import { APOD } from './graphql/queries/apod'; const App = () => { return ( <div> <Query query={APOD}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <div> <p>{data.apod.title}</p> <p>{data.apod.explanation}</p> <p>{data.apod.date}</p> <p><img src={data.apod.url} alt={data.apod.title}/></p> </div> ); }} </Query> </div> ); }; export default App;

Le composant Query est un observer, il se met donc à jour lorsqu'il obtient une réponse du serveur.

Maintenant que nous avons l'image du jour, nous souhaitons ajouter une image aléatoire qui vient de la bibliothèque d'images de la NASA. Je vais donc ajouter la query randonImage :

// graphql/queries/randomImage.js import gql from 'graphql-tag'; export const RANDOM_NASA_IMAGE = gql` query RANDOM_NASA_IMAGE($search: String!) { randomImage(search: $search) { title url description } } `;

Et voici notre composant App :

import React from 'react'; import { Query } from 'react-apollo'; import { APOD } from './graphql/queries/apod'; import { RANDOM_NASA_IMAGE } from './graphql/queries/randomImage'; const App = () => { return ( <div> <Query query={APOD}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <div className={'apod'}> <p>{data.apod.title}</p> <p>{data.apod.explanation}</p> <p>{data.apod.date}</p> <p><img src={data.apod.url} alt={data.apod.title}/></p> </div> ); }} </Query> <Query query={RANDOM_NASA_IMAGE} variables={{ search: 'raccoon' }}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <div className={'random'}> <p>{data.randomImage.title}</p> <p>{data.randomImage.description}</p> <p><img src={data.randomImage.url} alt={data.randomImage.title}/></p> </div> ); }} </Query> </div> ); }; export default App;

Pour information, avec GraphQL, nous pouvons faire plusieurs requêtes en un appel réseau au serveur, et c'est le serveur qui se chargera d'aggréger les données pour nous renvoyer une réponse.

Et voilà ! Bravo à vous :) Nous avons un client / serveur Apollo avec les résultats attendus. Dans le chapitre suivant nous allons voir comment améliorer les performances de notre application.

Auteur(s)

Marie Minasyan

Marie Minasyan

Astronaute Raccoon @ ElevenLabs_🚀 De retour dans la Galaxie.

Voir le profil

Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !

Notre équipe d'experts répond à toutes vos questions.

Nous contacter

Découvrez nos autres contenus dans le même thème