Retour

GraphQL avec REST & gestion de cache

Tuto
10 mai 2019
30mn

Progression
3

Apollo client

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.


Articles sur le même thème

Découvrez Eleven Labs

Notre site pour mieux nous connaître

J'y vais

Contact

Eleven Labs - Paris

102, rue du Faubourg Saint Honoré

75008 Paris

Eleven Labs - Nantes

42, rue la Tour d'Auvergne

44200 Nantes

Eleven Labs - Montréal

1155, Metcalfe St Suite 1500

Montréal, QC H3B 2V6, Canada

business@eleven-labs.com

01.82.83.11.75