gpt4 book ai didi

node.js - useQuery 返回未定义,但在 gql Playground 上返回数据

转载 作者:行者123 更新时间:2023-12-03 12:11:08 26 4
gpt4 key购买 nike

"@apollo/react-hooks": "^3.1.3",
"apollo-client": "^2.6.8",

Apollo 客户端在 react 应用程序上返回未定义但在 gql 操场上返回数据,我不明白为什么它不能在客户端工作但在 graphql 操场上工作。

架构

我已经为用户查询定义了联合以进行错误处理。
type Query {
user(id: ID!): UserReturn!
}

union UserReturn = User | Error

type User {
id: ID!
username: String!
email: String
profileUrl: String
createdAt: Date
ads: [Doc!]!
}


type Error {
message: String
code: ID
}

查询解析器
 async user(_, { id }, { User }) {
console.log('query - User')
try {
await delay(1000 * 3)
const user = await User.findById(id).populate('userData')
console.log(user)
if (!user) return {
__typename: 'Error',
message: 'User not found.',
code: id
}

const { _id: id, username, email, createdAt, userData: { profileUrl } } = user

console.log(username)
return {
__typename: 'User',
id,
username,
email,
createdAt,
profileUrl
}
} catch (err) {
console.log(err)
return {
__typename: 'Error',
message: 'Something went wrong while getting user.',
code: LogBack(err, `query/user?id=${id}`, __filename)
}
}
}

在gql游乐场查询时

在 graphql 操场上,查询有效。

Screenshot from 2020-01-25 23-44-01_censored

客户端
 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

useQuery 运行但返回 undefiend。

最佳答案

请耐心等待这个答案很长 .
我也遇到了这个问题。似乎在使用片段(在本例中为内联)和接口(interface)时会出现问题。我设法通过将正确的内省(introspection)数据传递给 Apollo 的启发式片段匹配器来解决它(参见第 3 步)。
这是有关如何解决它的详分割步指南:
1 - 验证控制台警告。
验证您的控制台中是否有警告(这是发生在我身上的一个示例)。这些是与默认启发式片段匹配器冲突的字段:
Firefox Dev Console with warnings
阅读 Apollo 文档,我发现了以下内容:

By default, Apollo Client's cache will use a heuristic fragmentmatcher, which assumes that a fragment matched if the result includedall the fields in its selection set, and didn't match when any fieldwas missing. This works in most cases, but it also means that ApolloClient cannot check the server response for you, and it cannot tellyou when you're manually writing invalid data into the store usingupdate, updateQuery, writeQuery, etc. Also, the heuristic fragmentmatcher will not work accurately when using fragments with unions orinterfaces. Apollo Client will let you know this with a consolewarning (in development), if it attempts to use the default heuristicfragment matcher with unions/interfaces. TheIntrospectionFragmentMatcher is the solution for working withunions/interfaces, and is explained in more detail below.


v2 的更多信息:
https://www.apollographql.com/docs/react/v2.6/data/fragments/#fragments-on-unions-and-interfaces
v3 的更多信息:
https://www.apollographql.com/docs/react/data/fragments/#using-fragments-with-unions-and-interfaces
为了解决这个问题,我们需要将 IntrospectionResultData 传递给 Apollo 客户端(参见步骤 3)。但在此之前,我们需要生成文件或数据。
你有 3 个选项。手动或自动(远程或本地)执行此操作。
2 - 生成自省(introspection)文件
选择 一个 以下选项中的一个(所有选项最终都相同)。在选择一个之前阅读所有这些。
2.1 - 选项 A - 手动生成文件。
使用以下架构使其适应您自己的架构。
请注意,以下是 TypeScript 代码。删除 type如果您使用的是纯 JS。
请注意,在我的情况下,我的 .gql 文件中有一个以下方式的联合类型:
   # GraphQL code omitted. 
union PlanningResult = Planning | PlanningTechnical
// 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;

// For Apollo V3:

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

完成此操作后,继续执行第 3 步。
2.2 - 选项 B - 自动远程进近。
这是如果您在远程服务器中有您的架构并且您想获取它。这是直接从 Apollo Docs 中提取的脚本。对于自动方法,您可以按照 Apollo Docs 中的说明直接获取模式:
// 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!');
}
});
});
这将生成一个带有 __schema 的 json 文件。和适当的类型。完成此操作后,继续执行第 3 步。
2.3 - 选项 C - 自动本地方法
上面的选项对我来说很困难,因为我的架构在身份验证墙后面。幸运的是,我确实可以直接在本地访问 .gql 文件,并且能够生成自省(introspection)文件。继续阅读:
我们使用 graphql-code-generator为我们生成自省(introspection)文件。
转到您的后端代码,或您的 graphql.gql 文件所在的任何位置,然后执行以下操作:
  • 安装 GraphQL Code Generator :
  • yarn add graphql

    yarn add -D @graphql-codegen/cli
  • 运行初始化向导:
  • yarn graphql-codegen init
  • 填写详细信息(根据自己的情况调整)
    就我而言,我选择了:
  • 后端 - API 或服务器,使用 React 构建的应用程序
  • 你的架构在哪里? ./appsync/appSync.gql
  • 选择插件:片段匹配器(也可以随意选择其他插件......这是重要的!)
  • 文档:./appsync/generated/introspection.ts(这是您希望输出文件的位置)

  • 这将生成 codegen.yml这将包括 graphql-code-generator 的插件和配置运行。
    这是我的:
    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"

    我已经评论了对我们的使命不重要的部分。
    然后(非常重要!)运行:
    yarn install
    因为向导将包添加到我们的 package.json .
    然后,生成代码:
    yarn generate
    这将输出需要包含在 Apollo 中才能继续的 introspection.ts 文件。
    3 - 将自省(introspection)文件注入(inject) ApolloClient
    现在,在您的前端代码中,复制 introspection.ts文件到你的仓库(如果它还没有在那里),并包括它:
    注意:我已将文件重命名为 fragmentTypes.ts 并将其包含在 apollo 文件夹中:
    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 }),
    });

    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,
    });
    在此之后,您的控制台警告应该消失,查询和突变应该正常执行。

    关于node.js - useQuery 返回未定义,但在 gql Playground 上返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59920824/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com