5
votes

useQuery renvoie undefined, mais renvoie des données sur le terrain de jeu gql

 const { data } = useQuery(
    gql`query user($id: ID!) {
      user(id: $id) {
        __typename
        ... on User {
          id
          username
          email
          profileUrl
          createdAt
          # ads
        }
        ... on Error {
          message
          code
        }
      }
    }
    `,
    {
      variables: {
        id: userId
      }
    }
  );

  console.log(data) // undefined

7 commentaires

asynchrone, mauvaise utilisation, lire la documentation


@xadm où? Sur le résolveur?


dans le composant - les données PEUVENT être indéfinies jusqu'à ce qu'elles soient récupérées


Non, je viens de poster la requête d'utilisation uniquement, j'avais essayé avec onComplete aussi mais je ne suis toujours pas défini.


cela ne fonctionne pas de cette façon, lisez la documentation: apollographql.com/docs/react/data/queries


... et réagissez à la documentation des hooks, par useEffect , useEffect


après une erreur de journalisation, j'obtiens cette erreur [GraphQL error]: Message: Cannot query field "__resolveType" on type "AdsReturn"., Location: [object Object], Path: undefined Erreur [GraphQL error]: Message: Cannot query field "__resolveType" on type "AdsReturn"., Location: [object Object], Path: undefined


3 Réponses :


0
votes

quelque chose qui pourrait aider, vous savez où vous appelez {data}, vous pouvez également rechercher error et console.log ('Error:', error)

consultez la documentation de la requête du client apollo

quelque chose comme ça, et regardez le message d'erreur, ça devrait aider!

import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';

const GET_GREETING = gql`
  query getGreeting($language: String!) {
    greeting(language: $language) {
      message
    }
  }
`;

function Hello() {
    const { loading, error, data } = useQuery(GET_GREETING, {
    variables: { language: 'english' },
  });
  if (loading) return 'Loading...';
  if (error) return `Error! ${error.message}`;
  return <h1>Hello {data.greeting.message}!</h1>;
}


0 commentaires

0
votes

C'est un peu une réponse tardive mais j'ai eu le même problème où mon playGround a renvoyé une réponse correcte mais pas le hook useQuery.

Mon problème était que la variable donnée à la requête, dans votre cas «id», était de type String au lieu de Number.


0 commentaires

0
votes

S'il vous plaît, supportez-moi car cette réponse est longue .

J'ai également rencontré ce problème. Il semble que le problème survienne lors de l'utilisation de fragments (dans ce cas, en ligne) et d'interfaces. J'ai réussi à le résoudre en passant les données d'introspection correctes à l'Apollo's Heuristic Fragment Matcher (voir étape 3).

Voici un guide détaillé étape par étape sur la façon de le résoudre:

1 - Vérifiez les avertissements de la console.

Vérifiez qu'il y a des avertissements dans votre console (voici un exemple qui m'est arrivé). Voici les champs qui entrent en collision avec le matcher de fragments heuristiques par défaut:

Firefox Dev Console avec avertissements

En lisant la documentation Apollo, j'ai découvert ce qui suit:

Par défaut, le cache d'Apollo Client utilisera une correspondance heuristique de fragments, qui suppose qu'un fragment correspondait si le résultat incluait tous les champs de son jeu de sélection, et ne correspondait pas lorsqu'un champ était manquant. Cela fonctionne dans la plupart des cas, mais cela signifie également qu'Apollo Client ne peut pas vérifier la réponse du serveur pour vous, et il ne peut pas vous dire quand vous écrivez manuellement des données invalides dans le magasin à l'aide de update, updateQuery, writeQuery, etc. De plus, l'heuristique Fragment Matcher ne fonctionnera pas correctement lors de l'utilisation de fragments avec des unions ou des interfaces . Apollo Client vous le fera savoir avec un avertissement de console (en développement), s'il tente d'utiliser le matcher de fragments heuristiques par défaut avec les unions / interfaces. IntrospectionFragmentMatcher est la solution pour travailler avec des unions / interfaces, et est expliqué plus en détail ci-dessous.

Plus d'informations pour la v2 ici: https://www.apollographql.com/docs/react/v2.6/data/fragments/#fragments-on-unions-and-interfaces

Plus d'informations pour la v3 ici: https://www.apollographql.com/docs/react/data/fragments/#using-fragments-with-unions-and-interfaces

Pour résoudre ce problème, nous devons transmettre IntrospectionResultData au client Apollo (voir l'étape 3). Mais avant cela, nous devons générer le fichier ou les données.

Vous avez 3 options. Faites-le manuellement ou automatiquement (à distance ou en local).

2 - Générer le fichier d'introspection

Choisissez l' une des options ci-dessous (elles finissent toutes par être identiques). Lisez-les tous avant d'en choisir un.

2.1 - Option A - Générer le fichier manuellement.

Utilisez le schéma suivant pour l'adapter au vôtre. Notez que ce qui suit est du code TypeScript. Supprimez le type si vous utilisez JS ordinaire.

Veuillez voir que dans mon cas, j'avais dans mon fichier .gql un type d'union de la façon suivante:

For V3:
import { InMemoryCache, ApolloClient } from '@apollo/client';
// In case you used graphql-code-generator
// import introspectionQueryResultData from './apollo/fragmentTypes';
// The file we just generated. If it's a .json file 
// remember to include the .json extension
import possibleTypes from './path/to/possibleTypes.json';

const cache = new InMemoryCache({
  possibleTypes,
});
const client = new ApolloClient({
  // ...other arguments...
  cache,
});
For V2:
import ApolloClient from 'apollo-client/ApolloClient';
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import { InMemoryCache } from 'apollo-cache-inmemory/lib/inMemoryCache';
// The file we just generated. If it's a .json file 
// remember to include the .json extension
import introspectionQueryResultData from './apollo/fragmentTypes';

const fragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData,
});

export const globalClient = new ApolloClient({
  link,
  cache: new InMemoryCache({ fragmentMatcher }),
});

yarn generate

Une fois que vous avez fait cela, passez à l'étape 3.

2.2 - Option B - Approche automatique à distance.

C'est si vous avez votre schéma sur un serveur distant et que vous souhaitez le récupérer. Il s'agit d'un script extrait directement des Apollo Docs. Pour l'approche automatique, vous pouvez récupérer le schéma directement comme indiqué dans la documentation Apollo:

yarn install

Cela générera un fichier json avec le __schema et les types appropriés. Une fois que vous avez fait cela, passez à l'étape 3.

2.3 - Option C - Approche locale automatique

Les options ci-dessus étaient difficiles pour moi car j'avais mon schéma derrière un mur d'authentification. Heureusement, j'ai eu un accès local direct au fichier .gql et j'ai pu générer le fichier d'introspection. Continuer à lire:

Nous utilisons graphql-code-generator pour générer le fichier d'introspection pour nous.

Accédez à votre code back-end, ou à l'endroit où se trouve votre fichier graphql.gql, et faites:

  1. Installez le générateur de code GraphQL :
overwrite: true
schema: "./appsync/appSync.gql"
# documents: "./appsync/**/*.gql"
generates:
  ./appsync/generated/introspection.ts:
    plugins:
      # - "typescript"
      # - "typescript-operations"
      # - "typescript-resolvers"
      # - "typescript-react-apollo"
      - "fragment-matcher"
    config:
    # NOTE: Remember to specify the CORRECT Apollo Client Version
      apolloClientVersion: 2.6
  ./graphql.schema.json:
    plugins:
      - "introspection"

  1. Exécutez l'assistant d'initialisation:
yarn graphql-codegen init
  1. Remplissez les détails (adaptez-les aux vôtres) Dans mon cas, j'ai sélectionné:
  • Backend - API ou serveur, application construite avec React
  • Où est votre schéma? ./appsync/appSync.gql
  • Choisissez des plugins: Fragment Matcher (N'hésitez pas à sélectionner d'autres plugins également ... c'est le plus important!)
  • document: ./appsync/generated/introspection.ts (C'est ici que vous voulez que le fichier soit sorti)

Cela générera un codegen.yml qui inclura les plugins et la configuration pour le graphql-code-generator à exécuter.

C'est à moi:

yarn add graphql

yarn add -D @graphql-codegen/cli

J'ai commenté les parties qui ne sont pas essentielles pour notre mission.

Puis (très important!) Exécutez:

// This is for V2 only, for V3 use the link down below (They're not the same!).

// For V2: https://www.apollographql.com/docs/react/v2.6/data/fragments/#fragments-on-unions-and-interfaces
// For V3 please, go to https://www.apollographql.com/docs/react/data/fragments/#generating-possibletypes-automatically

const fetch = require('node-fetch');
const fs = require('fs');

fetch(`${YOUR_API_HOST}/graphql`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    variables: {},
    query: `
      {
        __schema {
          types {
            kind
            name
            possibleTypes {
              name
            }
          }
        }
      }
    `,
  }),
})
  .then(result => result.json())
  .then(result => {
    // here we're filtering out any type information unrelated to unions or interfaces
    const filteredData = result.data.__schema.types.filter(
      type => type.possibleTypes !== null,
    );
    result.data.__schema.types = filteredData;
    fs.writeFile('./fragmentTypes.json', JSON.stringify(result.data), err => {
      if (err) {
        console.error('Error writing fragmentTypes file', err);
      } else {
        console.log('Fragment types successfully extracted!');
      }
    });
  });

Parce que l'assistant ajoute des packages à notre package.json .

Ensuite, générez le code:

// For Apollo V3:

      export interface PossibleTypesResultData {
        possibleTypes: {
          [key: string]: string[]
        }
      }
      const result: PossibleTypesResultData = {
  "possibleTypes": {
    "PlanningResult": [
      "Planning",
      "PlanningTechnical"
    ]
  }
};
      export default result;
    

Cela affichera le fichier introspection.ts qui doit être inclus dans Apollo pour continuer.

3 - Injectez le fichier d'introspection dans ApolloClient

Maintenant, dans votre code frontal, copiez le fichier introspection.ts dans votre référentiel (s'il ne s'y trouve pas déjà) et incluez-le:

Remarque: j'ai renommé mon fichier fragmentTypes.ts et l'ai inclus dans le dossier apollo:

// For Apollo V 2.x
export interface IntrospectionResultData {
  __schema: {
    types: {
      kind: string;
      name: string;
      possibleTypes: {
        name: string;
      }[];
    }[];
  };
}

const result: IntrospectionResultData = {
  __schema: {
    types: [
      {
        kind: 'UNION',
        name: 'PlanningResult',
        possibleTypes: [
          {
            name: 'Planning',
          },
          {
            name: 'PlanningTechnical',
          },
        ],
      },
    ],
  },
};
export default result;

   # GraphQL code omitted. 
  union PlanningResult = Planning | PlanningTechnical

Après cela, les avertissements de votre console devraient disparaître et les requêtes et mutations devraient fonctionner normalement.


0 commentaires