Catégories
Astuces et Design

Variables réactives dans GraphQL Apollo Client – Smashing Magazine

A propos de l'auteur

Daniel Don est un développeur de logiciels qui aime partager ses connaissances et expliquer des sujets apparemment difficiles avec des exemples relatables. Il habite à Port Harcourt…
Plus à propos
Daniel

Les variables réactives fonctionnent avec GraphQL Apollo et vous offrent les mêmes fonctionnalités avec Redux ou l'API de contexte sans la complexité ou les couches supplémentaires fournies avec ces autres outils. Une variable réactive dans GraphQL Apollo est facile à utiliser et ne nécessite pas autant de processus de configuration que Redux.

Dans cet article, nous verrons comment configurer des variables réactives, comment les politiques de cache GraphQL entrent en place pour définir la lecture et les écritures dans le cache, et fournirons la possibilité aux développeurs d'ajouter des types qui existent uniquement du côté client. que nous pouvons structurer les requêtes pour les variables côté client de la même manière que nous le pouvons pour les données GraphQL distantes. Après en avoir appris plus sur les principes fondamentaux des variables réactives, nous allons créer une application simple qui bascule le thème de notre application en mode sombre ou en mode clair en fonction de la valeur de notre variable réactive. Nous examinerons comment interroger une variable réactive, comment mettre à jour la valeur stockée dans une variable réactive et comment le changement de valeur déclenche des mises à jour dans les composants qui dépendent de la variable réactive pour que certaines actions se produisent.

Le public cible de cet article comprendrait les développeurs de logiciels qui utilisent déjà GraphqQL avec des outils de gestion d'état tels que Context API ou Redux et désireux d'explorer un nouveau modèle de gestion de l'état de gestion dans GraphQL, ou les débutants en GraphQL qui recherchent des moyens efficaces de gérer globalement partagé état local dans GraphQL sans rendre les choses trop compliquées avec des outils externes. Pour suivre cela, vous devez également avoir une connaissance existante de ReactJS et CSS.

Une introduction rapide à GraphQL

Avec GraphQL, vous obtenez exactement ce dont vous avez besoin, ainsi que les données renvoyées et structurées selon vos besoins.

«GraphQL est un langage de requête pour les API et un moteur d'exécution pour répondre à ces requêtes avec vos données existantes. GraphQL fournit une description complète et compréhensible des données de votre API, donne aux clients le pouvoir de demander exactement ce dont ils ont besoin et rien de plus, facilite l'évolution des API au fil du temps et permet des outils de développement puissants. »

– Site Web GraphQL

Qu'est-ce que Apollo Client dans GraphQL?

Apollo Client vous aide à éviter de suivre manuellement les états de chargement et d'erreur. Il offre également la possibilité d'utiliser GraphQL avec des modèles React modernes tels que des hooks, etc.

«Apollo Client est une bibliothèque complète de gestion d'état pour JavaScript qui vous permet de gérer à la fois les données locales et distantes avec GraphQL. Utilisez-le pour récupérer, mettre en cache et modifier les données d'application, tout en mettant automatiquement à jour votre interface utilisateur. »

– «Présentation d'Apollo Client», Apollo Docs

Définissons ici quelques termes que vous devrez comprendre pour avancer:

  • Variable
    Une variable est un nom que vous donnez à un emplacement mémoire affecté où une valeur est stockée. Le nom de la variable est utilisé comme référence à la valeur qui y est stockée lorsque vous devez l'utiliser.
  • Réactivité
    Nous expliquerons la réactivité comme quelque chose qui déclenche un changement sur ses dépendants lorsqu'une mise à jour lui est transmise. Comme l'état local dans React déclenche les mises à jour des composants, les variables réactives d'Apollo GraphQL déclenchent également automatiquement les mises à jour des composants en fonction des modifications.

La gestion de l'état est une partie très importante de la création d'une application moderne. Avoir un état global est important lorsque différents composants ou écrans nécessitent l'accès à la même valeur d'état et déclenchent éventuellement des changements lorsque cet état particulier est modifié.

Dans la section suivante, nous verrons comment configurer une variable réactive.

Écrire notre première variable réactive

Voici à quoi ressemble une variable réactive:

import { makeVar } from '@apollo/client';

const myReactiveVariable = makeVar(/** An initial value can be passed in here.**/)

le makeVar est importé d'Apollo Client et est utilisé pour déclarer notre variable réactive. le makeVar prend une valeur initiale que la variable réactive contiendrait. La facilité de construction d'une variable réactive est étonnante.

Il existe deux façons de lire les données de notre variable réactive créée. Le moyen le plus simple est d'appeler notre variable réactive déclarée que nous avons créée ci-dessus, en tant que fonction sans argument:

const variable = myReactiveVariable();

Obtenir la valeur d'une variable réactive est aussi simple que cela. Dans le bloc de code ci-dessus, nous avons déclaré une variable contenant notre variable réactive qui a été appelée sans argument pour lire les données qu'elle contient déjà.

On peut également obtenir la valeur d'une variable réactive avec le useQuery syntaxe que nous utiliserions normalement pour récupérer des données distantes dans GraphQL. Pour expliquer comment nous pouvons procéder, examinons le type de cache et les règles de champ.

Politiques de type et de champ

Le type de cache et les politiques de champ vous aident à définir comment un champ spécifique de votre cache Apollo Client est lu et écrit. Pour ce faire, vous fournissez des stratégies de champ au constructeur de inMemoryCache. Chaque politique de champ est définie dans le typePolicy qui correspond au type qui contient le champ. Définissons un typePolicy appelé Query et définissez une politique de champ pour accéder à un champ appelé myReactiveVariable.

import { InMemoryCache } from '@apollo/client';

// Here we import our reactive variable which we declared in another
// component
import { myReactiveVariable } from './reactivities/variable.js';

// The field policies hold the initial cached state of a field.
export default new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        myReactiveVariable: {
          read() {
            return myReactiveVariable();
          }
        }
      }
    }
  }
})

Dans l'extrait de code ci-dessus, nous avons déclaré un type appelé Query et défini un champ appelé myReactiveVariable. Ensuite, nous avons ajouté un read fonction qui spécifie ce qui se passe lors de la lecture de la valeur mise en cache du champ. Voici ce qui se passe lorsque le myReactiveVariable la valeur mise en cache du champ est en cours de lecture:

Nous passons la variable réactive que nous avions déclarée dans un autre composant et importée ici comme valeur renvoyée par le champ.

Maintenant que nous avons défini notre typePolicies et fieldPolicies, allons-y et écrivons notre requête pour obtenir la valeur stockée dans notre variable réactive. Voici à quoi ressemblerait la requête:

import { gql } from "@apollo/client";

export const GET_REACTIVE_VARIABLE = gql`
  query getReractiveVariable{
    myReactiveVariable @client
  }
`

le gql La balise littérale de modèle que nous avons importée du client Apollo ci-dessus est utilisée pour écrire une requête GraphQL dans le client Apollo.

Le nom de la requête myReactiveVariable doit correspondre au nom de champ déclaré dans la stratégie de champ. Si vous avez utilisé GraphQL, vous remarquerez que ce modèle de requête est identique à la requête normale que vous écririez s'il s'agissait d'une API GraphQL distante que nous interrogions. La seule différence est la @client placé après le nom du champ. Cela demande à Apollo de résoudre cette requête particulière sur le client et non sur une API externe.

C'est ça! Nous avons mis en place avec succès notre première variable réactive. Le processus semble un peu long au début, mais par la suite, vous pouvez déclarer une nouvelle variable réactive en déclarant simplement la variable réactive et en ajoutant une politique de champ pour elle.

Pour récupérer la variable réactive, vous pouvez utiliser le useQuery accrochez n'importe quel composant là où vous en avez besoin.
Voici un exemple.

import { useQuery } from '@apollo/client';
import { GET_REACTIVE_VARIABLE } from 'FILE_PATH_TO_YOUR_QUERY_FILE';

const {loading, error, data} = useQeury(GET_DARK_MODE);

// you can track loading, error states, and data the same way with a normal query in Apollo

Dans le code ci-dessus, nous avons importé useQuery de @apollo/client. Ensuite, nous avons importé le GET_REACTIVE_VARIABLE requête du fichier à partir duquel il a été exporté.

Enfin, nous passons à la useQuery hook dans notre requête, et déstructure loading, error, et data à partir de cela.

Modifier une variable réactive

Le client Apollo offre une belle façon de modifier une variable réactive – en appelant la fonction retournée par makeVar et passez un seul argument à la fonction. L'argument passé est la nouvelle valeur que la variable réactive contiendra. Regardons un exemple ci-dessous où nous modifions notre variable réactive que nous avons déclarée ci-dessus:

import { myReactiveVariable } from 'PATH_TO_OUR_REACTIVE_VARIABLE_FILE'

myReactiveVariable("A new value is in!");

Dans le code ci-dessus, nous importons myReactiveVariable et nous la mettons à jour en appelant la variable et en plaçant la nouvelle valeur à l'intérieur.

Il est si facile de mettre à jour les valeurs d'une variable réactive. Une fois la valeur d'une variable réactive mise à jour, les actions correspondantes sont déclenchées dans les composants qui dépendent de la variable et l'interface utilisateur est ajustée automatiquement.

Dans la section suivante, nous allons créer une simple application de changement de thème qui fait passer les thèmes du mode sombre au mode clair en un clic. Le bouton change lui-même en fonction de la valeur du thème actuel. Cela nous aidera à rassembler tout ce que nous avons appris en construisant quelque chose qui illustre pleinement et simplement le concept de variables réactives et montre comment l'interface utilisateur est automatiquement déclenchée lorsque la variable réactive est mise à jour.

Voici à quoi ressemblera notre résultat:

(Grand aperçu)

Commençons.

Installer

Tout d'abord, nous créons une nouvelle application React.

npx create-react-app theme_toggle

Ensuite, installons les bibliothèques nécessaires dont nous avons besoin pour Apollo et GraphQL, y compris le react-feather bibliothèque pour obtenir nos icônes et react-router-dom pour configurer le routage

npm install @apollo/client graphql react-feather react-router-dom

Une fois que nous avons terminé toutes les installations, allons-y et configurons notre graphQL, y compris la définition de notre darkMode variable réactive.

Créez un dossier appelé graphql à l'intérieur de src dossier, puis créez un sous-dossier appelé réactivités pour héberger toutes les variables réactives. Voici à quoi ressemblerait l'arborescence des dossiers:
src> graphql> réactivités> themeVariable.js

J'ai décidé d'organiser notre structure de fichiers et de dossiers en simulant un cas d'utilisation réel, alors suivez-moi.
Allons-y pour déclarer notre variable réactive dans le themeVariable.js fichier que nous venons de créer:

import { makeVar, gql } from "@apollo/client";
export const darkMode = makeVar(false);

Ensuite, dans le même fichier, construisons notre requête pour obtenir notre variable réactive et spécifiez que la requête doit être résolue côté client. Nous pouvons décider de créer un dossier séparé pour héberger toutes nos requêtes, en particulier lorsque nous avons de nombreuses requêtes dans notre application, mais pour les besoins de ce tutoriel, nous allons écrire la requête dans le même fichier que la variable réactive et les exporter individuellement:

import { makeVar, gql } from "@apollo/client";

export const darkMode = makeVar(false);

// This is the query to get the darkMode reactive variable.
export const GET_DARK_MODE = gql`
  query getDarkMode{
    darkMode @client
  }
`

Dans le morceau de code ci-dessus, nous voyons à quel point il était simple de déclarer une variable réactive avec le makeVar() et passé une valeur initiale de false pour notre nouvelle variable. Ensuite, nous avons importé gql du client Apollo et l'a utilisé dans l'écriture de notre requête.

Ensuite, créons notre cache.js fichier et définissez nos politiques de type et de champ pour contrôler la manière dont les variables seront interrogées et structurées:

Créez un fichier appelé cache.js à l'intérieur de graphql dossier. À l'intérieur cache.js voici comment nous déclarons nos politiques:

import { InMemoryCache } from '@apollo/client';
import { darkMode } from './reactivities/themeVariable';

export default new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        darkMode: {
          read() {
            return darkMode();
          }
        }
      }
    }
  }
})

Dans le code ci-dessus, nous avons d'abord importé inMemoryCache du client Apollo, et nous avons importé notre variable réactive à partir du chemin du fichier où nous l'avons stockée.
Ensuite, nous avons créé une nouvelle instance de inMemoryCache et notre politique de terrain est définie à l'intérieur du typePolicy objet. Le code ci-dessus définit une politique de champ pour le darkMode champ sur le Query type.

Il y a une dernière étape pour terminer la configuration d'Apollo pour notre application React, nous devons créer un client.js fichier. le client.js fichier est un fichier que vous connaissez déjà si vous utilisez GraphQL auparavant. Il détient le ApolloClient constructeur qui serait finalement passé dans le ApolloProvider sur un fichier de niveau supérieur (généralement le fichier index.js). Notre fichier client.js doit être situé directement dans le src dossier.

src> client.js

import { ApolloClient } from '@apollo/client';
import cache from './graphql/cache';
const client = new ApolloClient({
  cache,
  connectToDevTools: true,
});
export default client;

Voici ce que nous avons fait ci-dessus. Nous avons importé ApolloClient. Ensuite, nous avons importé notre cache d'où il a été précédemment déclaré. À l'intérieur de notre ApolloClient constructeur, nous avons passé dans notre cache que nous avons importé et défini connectToDevTools comme true pour nous permettre d'utiliser les outils de développement Apollo dans notre navigateur.

Enfin, nous devons passer dans le nouveau ApolloClient instance que nous avons exportée en tant que client dans ApolloProvider dans notre top-niveau index.js fichier dans le src dossier. Ouvrez le index.js fichier et remplacez le code par celui-ci.

import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider } from '@apollo/client';
import './index.css';
import App from './App';
import client from './client';
ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);

Dans le bloc de code ci-dessus, nous avons enveloppé notre App composant avec le ApolloProvider et passé client (que nous avons importé) au fournisseur Apollo. Nous l'avons fait dans la portée de niveau supérieur afin que l'ensemble de notre application puisse accéder au ApolloProvider et le client.

Nous avons tout terminé avec succès dans la configuration d'Apollo et de la variable réactive. Vous remarquerez que beaucoup de choses que nous avons faites ici étaient liées à la configuration d'Apollo, ce que vous auriez toujours fait même si vous utilisiez Apollo avec une autre API externe pour gérer le contexte.

Puisque nous avons terminé avec tout ce dont nous avons besoin pour configurer Apollo et créer notre variable réactive, allons-y maintenant et configurons notre page et notre routage.

Nous n'aurions qu'un seul itinéraire vers une page appelée landingPage.jsx. À l'intérieur de src dossier, créez un dossier appelé pages pour héberger toutes les pages (dans notre cas, nous n'avons qu'une seule page) et créez un fichier appelé landingPage.jsx dedans.

src> pages> landingPage.jsx

À l'intérieur de notre page nouvellement créée, créons un composant fonctionnel avec un h1 balise contenant ou en-tête. Voici ce qu'il y aura dedans.

import React from 'react';

const LandingPage = () => {
  return (
    

Welcome to Theme Toggle Appliation!

) } export default LandingPage

Ensuite, créons notre composant bouton. À l'intérieur src, créez un dossier appelé composants et créez un button.jsx fichier.
src> composants> button.jsx

À l'intérieur de notre composant de bouton, voici les éléments à partir desquels nous devons importer des icônes react-feather, le useQuery crochet de apollo/client, notre requête et variable réactive du fichier à partir duquel elle a été exportée.

import React from 'react'
import { Moon, Sun } from 'react-feather';
import {  useQuery } from '@apollo/client';
import { GET_DARK_MODE, darkMode as reactiveDarkMode } from '../graphql/reactivities/themeVariable';

Dans le composant bouton, interrogeons notre client GraphQL avec le GET_DARK_MODE requête comme nous le ferions normalement dans GraphQL avec Apollo.

...

const ButtonComponent = () => {

  {loading, error, data} = useQuery(GET_DARK_MODE);

  return (...)
}

export default ButtonComponent;

Ensuite, nous voulons changer les boutons en fonction de la valeur booléenne de notre variable réactive qui sera renvoyée à partir des données. Pour ce faire, nous allons créer deux boutons et utiliser un opérateur ternaire pour les afficher conditionnellement en fonction de la valeur booléenne de notre variable réactive:

...

const ButtonComponent = () => {

  const {loading, error, data} = useQuery(GET_DARK_MODE);

  return (
    
{ data.darkMode ? ( ) :( ) }
) } export default ButtonComponent;

Dans le code ci-dessus, nous avons affiché les deux boutons conditionnellement avec l'opérateur ternaire pour afficher lorsque la valeur de data.darkMode est soit true ou false. Notre valeur initiale telle que déclarée dans notre themeVariable.js est false.

Remarque: N'oubliez pas que nous pouvons extraire darkMode des données car nous l'avons déclaré de cette façon dans notre politique de champ cache.js.

Nous avons ajouté du CSS aux boutons pour les rendre plus beaux et avons également ajouté les icônes importées de react-feather à chaque bouton.

Si vous avez remarqué que nous avons eu un onClick propriété passée dans chaque bouton qui a appelé toggleMode. Déclarons la fonction ci-dessus mais toujours dans le ButtonComponent:

...

const ButtonComponent = () => {

  const toggleMode = () => {
    console.log("Clicked toggle mode!")
  }

return (...)
}

export default ButtonComponent;

Actuellement, nous avons un console.log() à l'intérieur de toggleMode fonction. Dans une partie ultérieure de cet article, nous reviendrons pour écrire correctement cette fonction pour mettre à jour la valeur de la variable réactive.

Revenons maintenant à la ladingPage.jsx fichier que nous avons créé auparavant et ajoutez le bouton que nous venons de créer:

import React from 'react';
import ButtonComponent from '../components/button';

const LandingPage = () => {
  return (
    

Welcome to Theme Toggle Appliation!

) } export default LandingPage

Pour ajouter le bouton, nous l'avons simplement importé dans notre page et l'avons ajouté sous le h1 élément que nous avions déjà sur la page.

Voici à quoi ressemble notre application Web pour le moment.

(Grand aperçu)

Nous avons presque fini de créer notre application. Ensuite, modifions l'arrière-plan et la couleur du texte de la page dans le landingPage.jsx style pour être conditionnellement noir ou blanc en fonction de la valeur booléenne de notre variable réactive qui sera basculée dans le composant bouton plus tard. Pour ce faire, nous utiliserons également le useQuery hook pour obtenir la valeur actuelle de notre variable réactive.

Notre landingPage.jsx Le fichier ressemblera enfin à ceci:

import React from 'react'
import { useQuery } from '@apollo/client';
import ButtonComponent from '../components/button';
import { darkMode, GET_DARK_MODE } from '../graphql/reactivities/themeVariable';

const LandingPage = () => {
  const {loading, error, data} = useQuery(GET_DARK_MODE);
  return (
    

Welcome to Theme Toggle Appliation!

) } export default LandingPage

Faites attention à la façon dont nous changeons Couleur de l'arrière plan et Couleur du conteneur div en fonction de la valeur booléenne de la variable réactive renvoyée. Nous utilisons un opérateur ternaire pour définir le backgroundColor à black ou white en fonction de la valeur de data.darkMode. La même chose devrait être faite pour la valeur de color. C'est tout ce dont nous avons besoin pour landingPage.jsx composant.

La dernière chose que nous devrons faire pour que notre application fonctionne est de faire toggleMode fonction dans le composant bouton permettant de modifier la variable réactive en cliquant sur le bouton. Voyons comment modifier à nouveau une variable réactive, cette fois, dans un exemple d'application réel.

Modification d'une variable réactive

Comme nous l’avons appris précédemment, pour modifier une variable réactive, il suffit d’appeler la fonction renvoyée par makeVar et transmettez la nouvelle valeur à l'intérieur de celui-ci. Voici comment cela fonctionnera dans notre cas:

Accédez au composant bouton et procédez comme suit:

...
import { GET_DARK_MODE, darkMode } from '../graphql/reactivities/themeVariable';

const ButtonComponent = () => {

  const toggleMode = () => {
    darkMode(!darkMode)
  }

return (...)
}

export default ButtonComponent;

Tout d'abord, nous avons importé le GET_DARK_MODE requête et le darkMode variable réactive du fichier à partir duquel ils ont été exportés.

Ensuite, nous avons écrit une fonction de flèche pour toggleMode et appelé le darkMode fonction renvoyée par makeVar et passé une inversion de la valeur actuelle qu'elle contenait comme nouvelle valeur que la variable réactive portera quand elle sera cliquée.

Toute notre application est alimentée par une variable réactive et une fois qu'il y a un changement de la valeur contenue dans la variable réactive, chaque composant ou page dépendant de cette variable pour qu'une action se déclenche est mis à jour et l'interface utilisateur est mise à jour avec les modifications actuelles. Nous avons échappé à tous les obstacles liés aux fonctions de répartition et aux autres étapes ambiguës que nous devons suivre lors de l'utilisation d'autres bibliothèques de gestion d'état comme Redux ou Context API.

Conclusion

Les variables réactives du client Apollo vous offrent un modèle de requête simple, facile à utiliser, facile à mettre à jour et cohérent avec l'interrogation d'une API GraphQL distante régulière. Apprendre à utiliser des variables réactives pour la gestion des états est un plus pour vous car cela vous donne la flexibilité de choisir parmi de nombreux outils. Les variables réactives vous permettraient de gérer l'état global partagé localement entre les composants sans le passe-partout supplémentaire qui serait généralement fourni avec les bibliothèques de gestion d'état dominantes qui existent déjà.

  • Consultez le code terminé sur GitHub.
Éditorial fracassant(ks, ra, il)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *