[RAILS] Je suis parfaitement conscient de la commodité de graphql-code-generator partie 2

introduction

Aujourd'hui et aujourd'hui, les rails avant React + back ...

Donc, cette fois, dans le prolongement de je suis parfaitement conscient de la commodité du générateur de code graphql, les «mutations» telles que l'enregistrement et la suppression, etc. Je ferai la part de.

Pour le moment, essayez selon la formule d'Apollo

Tout d'abord, nous allons créer un mécanisme pour ajouter TODO.

Nous avons préparé un champ de texte supplémentaire. Entrez une valeur ici et entrez exécutera un traitement supplémentaire.

スクリーンショット 2020-09-22 12.44.46.png

src/App.tsx


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

...

+const ADD_TODO = gql`
+  mutation addTodo($name: String!) {
+    addTodo(input: { name: $name }) {
+      todo {
+        id
+        name
+      }
+    }
+  }
+`;

 const App = () => {
   const { loading, data } = useTodosQuery();
+  const [addTodo] = useMutation(ADD_TODO);

...
         </p>
+        <input
+          type="text"
+          onKeyPress={(e) => {
+            if (e.key === "Enter") {
+              addTodo({ variables: { name: e.currentTarget.value } });
+            }
+          }}
+        />
         {loading ? (
...

Nous avons créé un mécanisme qui vous permet de saisir des caractères et d'effectuer un traitement supplémentaire avec enter.

Si vous rechargez l'écran après avoir appuyé sur Entrée, vous pouvez voir que TODO a été ajouté.

スクリーンショット 2020-09-22 14.18.50.png

Comme vous ne pouvez pas voir le mouvement sans recharger, en plus du traitement supplémentaire, effacez le champ de saisie et réacquérir les informations de la liste.

src/App.tsx


...
-  const { loading, data } = useTodosQuery();
+  const { loading, data, refetch } = useTodosQuery();
-  const [addTodo] = useMutation(ADD_TODO);
+  const [addTodo] = useMutation(ADD_TODO, {
+    update() {
+      refetch();
+    },
+  });

...

           onKeyPress={(e) => {
             if (e.key === "Enter") {
               addTodo({ variables: { name: e.currentTarget.value } });
+              e.currentTarget.value = "";
             }
           }}

Aucune erreur particulière liée au type ne s'est produite.

Essayez de le rendre un peu plus pratique

Exécutez le processus d'enregistrement sans rien entrer et mettez en place un mécanisme qui provoque une erreur.

Ajout d'un champ d'erreur de validation à Todo pour inclure les valeurs suivantes dans la réponse:

"errors":[{"field":"name","error":"blank"}]

Nous avons également ajouté un champ result (booléen) pour voir si le résultat du processus a réussi.

Si result est vrai, rechargez la liste, et si faux, créez un mécanisme pour afficher les informations d'erreur avec ʻalert`.

src/App.tsx


 const ADD_TODO = gql`
   mutation addTodo($name: String!) {
     addTodo(input: { name: $name }) {
       todo {
         id
         name
+        errors {
+          field
+          error
+        }
      }
+      result
    }
  }
`;

src/App.tsx


   const [addTodo] = useMutation(ADD_TODO, {
-    update() {
-      refetch();
-    },
-  });
+    update(
+      _cache,
+      {
+        data: {
+          addTodo: {
+            todo: { errors },
+            result,
+          },
+        },
+      }
+    ) {
+      if (result) {
+        refetch();
+      } else {
+        errors.forEach(({ field, error }) => {
+          alert(`${field} ${error}`);
+        });
+      }
+    },
+  });

Une erreur s'est produite car le type d'erreurs n'a pas été déclaré.

スクリーンショット 2020-09-22 16.10.28.png

Je vais déclarer le type.

type ValidationErrorType = {
  field: string;
  error: string;
};
-errors.forEach(({ field, error }) => {
+errors.forEach(({ field, error }: ValidationErrorType) => {
  alert(`${field} ${error}`);
});

L'erreur a été résolue et les messages d'erreur de validation peuvent maintenant être vus avec ʻalert`.

スクリーンショット 2020-09-22 16.15.46.png

Comme la dernière fois, j'utiliserai graphql-code-generator pour le nettoyer.

Utiliser graphql-code-generator

D'abord à partir des paramètres

Créez un répertoire pour les «mutations» séparément des «requêtes» et stockez-y la requête créée cette fois.

codegen.yml


-documents: ./graphql/queries/*.graphql
+documents:
+  - ./graphql/mutations/*.graphql
+  - ./graphql/queries/*.graphql

graphql/mutations/add_todo.graphql


mutation addTodo($name: String!) {
  addTodo(input: { name: $name }) {
    todo {
      id
      name
      errors {
        field
        error
      }
    }
    result
  }
}

Maintenant, lorsque vous exécutez yarn generate, vous aurez ʻuseAddTodoMutation pour ajouter TODO à src / types.d.ts`.

Réécrivons le processus supplémentaire en utilisant ʻuseAddTodoMutation`.

-import { useTodosQuery } from "./types.d";
+import { useTodosQuery, useAddTodoMutation } from "./types.d";

+const [addTodo] = useMutation(ADD_TODO, {
+const [addTodo] = useAddTodoMutation({

Hmm? Une erreur est survenue.

スクリーンショット 2020-09-22 21.01.17.png

Apparemment, "data" peut être "nul" ou "non défini".

Dans cet esprit, je vais le réécrire un peu.

const [addTodo] = useAddTodoMutation({
  update(_cache, { data }) {
    const result = data?.addTodo?.result || false;
    const errors = data?.addTodo?.todo.errors || [];

    if (result) {
      refetch();
    } else {
      errors.forEach((e) => {
        if (e) alert(`${e.field} ${e.error}`);
      });
    }
  },
});

Il fallait quelques ajustements, mais c'est rafraîchissant en termes de source car il ne nécessite plus de requêtes et de déclarations de type: thumbsup:

Essayez de mettre en œuvre le processus de suppression de la même manière

Bien que ce soit une idée approximative, un bouton de suppression est fourni à côté de chaque TODO afin que le processus de suppression puisse être exécuté.

スクリーンショット 2020-09-27 23.50.47.png

graphql/mutations/del_todo.graphql


mutation delTodo($id: ID!) {
  delTodo(input: { id: $id }) {
    todo {
      id
    }
  }
}

Vous devez obtenir un identifiant pour identifier le TODO à supprimer.

Dans graphql / queries / todos.graphql, seul le nom de TODO est acquis, donc modifiez-le pour qu'il prenne ʻid`.

graphql/queries/todos.graphql


 query todos {
   todos {
+    id
     name
   }
 }

Lancer yarn generate a créé la fonction ʻuseDelTodoMutation dans src / types.d.ts`.

Utilisez cette ʻuseDelTodoMutation pour permettre l'exécution du processus de suppression lorsque le bouton supprimer` est cliqué.

src/App.tsx


-import { useTodosQuery, useAddTodoMutation } from "./types.d";
+import { useTodosQuery, useAddTodoMutation, useDelTodoMutation } from "./types.d";


+const [delTodo] = useDelTodoMutation({
+  update() {
+    refetch();
+  }
+});


-{data && data.todos.map(({ name }, i) => <li key={i}>{name}</li>)}
+{data && data.todos.map(({ id, name }, i) => <li key={i}>{name}<button onClick={() => delTodo({ variables: { id } })}>Supprimer</button></li>)}

J'ai pu facilement implémenter le processus de suppression: tada:

add-del.gif

finalement

Puisque l'acquisition de liste, le traitement d'addition et le traitement de suppression sont implémentés sur un écran et un composant, il se peut que le fichier soit légèrement plus volumineux.

Il est peut-être possible de définir la définition de type et les informations de requête dans un autre fichier et d'utiliser ʻimport`, mais je pense que la gestion peut devenir plus compliquée s'il y a plusieurs personnes.

Je pensais que si cela était développé selon les règles de graphql-code-generator dans un sens, ce problème serait résolu.

Cette fois, je l'ai implémenté comme un exemple assez petit, donc je n'ai ressenti aucun obstacle à l'introduction. Je pense que c'est un outil LGTM: thumbsup:

Recommended Posts

Je suis parfaitement conscient de la commodité de graphql-code-generator partie 2
Modifier seulement une partie du texte
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
J'ai lu la source de Long
J'ai lu la source de Short
J'ai lu la source de Byte
J'ai lu la source de String
J'ai étudié le traitement interne de Retrofit
[jour: 5] J'ai résumé les bases de Java
J'ai vérifié la partie de java.net.URL # getPath
J'ai compris les bases de la saisie de caractères
Enregistrement d'image? Bien sûr, je ne peux pas (peut) ~ part2 ~
[Java] La partie déroutante de String et StringBuilder
J'ai comparé les caractéristiques de Java et .NET
Je veux var_dump le contenu de l'intention
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
J'ai vérifié le nombre de taxis avec Ruby
Essayez Progate Free Edition [Java I]
La partie à laquelle j'étais accro dans "Introduction à Ajax dans les applications Web Java" de NetBeans