为啥 GraphQL 片段在查询中需要 __typename?

Posted

技术标签:

【中文标题】为啥 GraphQL 片段在查询中需要 __typename?【英文标题】:Why do GraphQL fragments need __typename in queries?为什么 GraphQL 片段在查询中需要 __typename? 【发布时间】:2018-01-12 12:51:11 【问题描述】:

我找不到或我在错误的地方寻找有关片段如何匹配的任何文档。当我使用香草 Apollo 客户端时,如果我在使用片段时关闭 addTypename 的选项,我会收到警告 heuristic fragment matching going on!,如果我添加它,它就会消失,但我的响应包含许多 __typename 字段,我没有需要。他们为什么提供帮助?

【问题讨论】:

也许这不能完全满足您的问题,但__typename 似乎是 Apollo 能够匹配其缓存中的片段的唯一踪迹。我认为要解决这个问题,您不需要传递addType: true - 保持它为假,而是尝试将__typename 添加到您的片段中。 【参考方案1】:

原因是 ApolloClient 和 Relay 一样,使用全局存储在客户端缓存你的数据。

为了为您执行此操作,需要全局 ID。出于某种原因,全局 id 不是人们考虑的问题,事实上,这是人们在切换到 Relay 时一直抱怨的问题。

ApolloClient 对此有一个聪明的解决方案! (如果我错了,Apollo 团队会纠正我)它们允许您定义您的记录如何在商店中键入!默认情况下,它使用 typename 和 id 创建 Relay 建议您创建的那种全局 ID。这就是他们需要类型名称的原因。

由于您在查询中关闭了 typename,Apollo 会做一些聪明的事情来尝试找出类型(以及存储中的键)。这些聪明的东西可能会给你带来麻烦。

如果您想创建自己的全局 id 而不是使用所有这些聪明的东西,您可以像这样指定它:

const cache = new InMemoryCache(
  dataIdFromObject: object => object.key || null
);

https://www.apollographql.com/docs/react/advanced/caching.html#normalization

【讨论】:

以上是关于为啥 GraphQL 片段在查询中需要 __typename?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中发送带有片段的 graphql 查询

GraphQL Relay 自省查询失败:“查询”类型上的未知字段“__type”

在 Java 的 GraphQL 查询中添加片段

你如何在 python 中处理 graphql 查询和片段?

使用 _id 字符串的 GraphQL 查询,对象 ID 存储在 MongoDB 中

在graphql中嵌套片段