我应该如何使用 Apollo Client 和 Link Rest 从 GraphQL 中的同一响应中查询和匹配数据?
Posted
技术标签:
【中文标题】我应该如何使用 Apollo Client 和 Link Rest 从 GraphQL 中的同一响应中查询和匹配数据?【英文标题】:How should I query and match data from the same response in GraphQL with Apollo Client and Link Rest? 【发布时间】:2019-12-01 13:00:45 【问题描述】:我有以下疑问:
const getPage = gql`
query Page($path: String!)
page(path: $path) @rest(type: "Page", path: "args.path")
blocks @type(name: Block)
name
posts @type(name: Post)
body
author
authors @type(name: Author)
name
在blocks.posts.author
中只有一个AuthorId
。 authors 对象包含所有可用的作者。
我想用它的对应对象替换/匹配AuthorId
。是否可以在一个查询中执行此操作?
我也不介意仅对 Author 进行单独查询(将缓存提取,不会发出新请求),但我仍然不知道如何通过 2 个查询匹配它。
示例 API 响应
blocks: [
posts: [
id: 1,
title: 'My post',
author: 12,
]
],
authors: [
id: 12,
name: 'John Doe'
]
我想要通过 1 个查询使 post
中的 author
成为完整的作者对象。
【问题讨论】:
根据指令,您似乎正在使用apollo-client
和apollo-link-rest
,但这在您的问题中未提及,也未在标签中反映出来。
谢谢,已添加。
我添加了一个应该可行的答案,尽管自从我使用该链接以来已经有一段时间了。如果您要包装一个非常基本的 REST 端点,这是一个简洁的库,但您应该考虑设置一个单独的 GraphQL 服务器作为网关,而不是用于更复杂的情况。这使您在如何解析字段方面具有更大的灵活性,并为缓存 REST 响应和其他功能开辟了道路,这些功能是 apollo-link-rest 无法实现的。
缓存将在浏览器级别使用 SW 解决,给我们更多的控制权。我们试图拥有您发布的此类解决方案,但您所拥有的需要一个单独的端点,因为我可以看到我们没有。我们无法改变这一点,它是一个像这样工作的 php API,我们必须处理它:)
【参考方案1】:
很好的问题。使用 GraphQL,您可以扩展任何字段并从中选择所需的确切子字段,因此,如果您也在后端使用 GraphQL,这将不是问题。您可以在此处执行一些解决方法:
如果所有作者对象都在您的 Apollo 缓存中,并且您可以访问每个作者的 id,则可以使用 ApolloClient.readFragment 访问其他属性,如下所示:
const authorId = ...; // the id of the author
const authorInfo = client.readFragment(
id: authorId,
fragment: gql`
fragment AuthorInfo on Author
id
name
# anything else you want here
`,
);
虽然值得注意的是,对于问题中的原始查询,如果您将所有 Author 对象作为查询的属性,您可以只使用 javascript 操作从 Author id 转到对象。
const authorId = ...; // the id of the author
data.page.authors.find(author => author.id === authorId);
【讨论】:
感谢您的详细回答,但这对我没有帮助。您的第一个建议假设我已经拥有我没有的 ID,一切都在同一个响应中。第二个是我们正在做并希望避免的事情,因为它会导致某些问题。 @wintercounterPost
和Author
的类型定义是什么?根据您的问题,我假设 Post.author
是对作者的一些独特引用,无论是按名称还是 ID。您可以将 Apollo 缓存配置为使用任何字段(或字段组合)作为唯一标识符,因此第一种方法应该仍然有效。更多信息在这里:apollographql.com/docs/react/advanced/caching/#normalization
是的,您没看错,但authors
也将出现在相同的 API 响应中。所以回复基本是posts: [], authors: []
,所以之前没有作者ID。
添加了示例 API 响应。【参考方案2】:
以下应该可以工作。
首先,使用@export 指令将作者ID 作为变量捕获。然后添加一个名称不是author
的新字段,并使用路径中的导出变量用@rest 装饰它。
所以查询看起来像这样:
query Page($path: String!)
page(path: $path) @rest(type: "Page", path: "args.path")
blocks @type(name: Block)
name
posts @type(name: Post)
body
author @export(as: "authorId")
authorFull @rest(
path: '/authors/exportVariables.authorId'
type: 'Author'
)
name
authors @type(name: Author)
name
您可以使用fieldNameNormalizer
option 将响应中的author
属性重命名为具有不同名称的字段(例如authorId
)。理想情况下,这仍然适用于上述内容,因此您可以避免使用像 authorFull
这样的奇怪字段名称,但 apollo-link-rest 有点不稳定,所以没有承诺。
【讨论】:
以上是关于我应该如何使用 Apollo Client 和 Link Rest 从 GraphQL 中的同一响应中查询和匹配数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 localStorage 与 apollo-client 和 reactjs 一起使用?
如何使用 Apollo 工具为查询生成 Typescript 类型,包括 Apollo @client 和 @rest 指令?