【问题标题】:Update Apollo cache after object creation创建对象后更新 Apollo 缓存
【发布时间】:2020-02-12 14:39:01
【问题描述】:

在突变后更新 Apollo InMemoryCache 的所有不同方法是什么? From the docs,我看到了:

  1. Id-based updates Apollo 自动执行
    • 仅针对现有对象的单一更新发生。
    • 需要一个唯一标识每个对象的id 字段,或者缓存必须配置一个提供唯一标识符的dataIdFromObject 函数。
  2. “手动”缓存更新通过update functions
    • 对象创建、删除或更新多个对象时需要。
    • 涉及调用 cache.writeQuery 并提供详细信息,包括应影响哪个查询以及应如何更改缓存。
  3. refetchQueries 选项传递给useMutation 挂钩
    • 调用代码说明应该从 API 重新获取哪些查询,Apollo 进行获取,结果替换给定查询的缓存中的任何内容。

还有其他我遗漏的方法,或者我对上述方法有什么误解吗?

我很困惑,因为我一直在阅读一个项目的代码,该项目使用 Apollo 进行各种突变,包括创建和删除,但我没有看到对 cache.writeQuery 的任何调用,也没有看到对 @987654333 的任何使用@。如果没有其中任何一个,缓存如何在创建和删除后更新?

在我自己对 Apollo 的有限经验中,缓存不会在对象创建或删除后自动更新,即使我定义了 dataIdFromObject。我必须自己通过编写更新函数来更新缓存。

所以我想知道是否有一些我错过了让 Apollo 为我处理它的秘密配置。

【问题讨论】:

  • 如果我们正在讨论更新已在缓存中的项目,那么,不,您不需要做任何额外的事情,只要该项目具有唯一的 id_id字段您提供自定义dataIdFromObject 实现。有很多方法可以弄乱您的客户端配置,但是如果不查看代码就不可能确切地知道出了什么问题。您应该提供minimal reproducible example 的代码,其中没有发生这种情况,否则这个问题的答案就是“不”。
  • 嘿,感谢您的评论。我的问题实际上是关于对象的创建——而不是缓存中已经存在的项目。如果没有cache.writeQueryrefetchQueries,缓存如何知道对象创建?
  • 对不起,我误解了你的问题。但是,您的断言通常仍然是正确的——创建的项目不会插入到缓存中的任何列表中,因为根据业务逻辑,Apollo 不知道它是否属于任何现有列表。我可以想象的 only 例外是对象创建突变是否返回相关列表的父字段。同样,如果有些代码的行为不是这样,最好分享一下。
  • 我认为父字段就是答案——它与我在对象创建后在 API 响应中看到的一致。谢谢!如果您想添加一个简要解释正在发生的事情的答案,我很乐意接受。我无法举一个最小的例子,因为我有一个大型的现有代码库,表现出良好的行为,还不错......它只是没有按照我阅读 Apollo 文档时所期望的方式编写。

标签: graphql apollo react-apollo apollo-client


【解决方案1】:

创建或删除节点并让 Apollo 自动更新缓存以反映更改的唯一方法是返回包含更新的 List 字段的任何字段的父字段。例如,假设我们有这样的架构:

type Query {
  me: User
}

type User {
  id: ID!
  posts: [Post!]!
}

type Post {
  id: ID!
  body: String!
}

按照惯例,如果我们有一个添加新帖子的突变,突变字段将返回创建的帖子。

type Mutation {
  writePost(body: String!): Post!
}

但是,我们可以让它返回已登录的用户(me 字段返回的内容相同):

type Mutation {
  writePost(body: String!): User!
}

通过这样做,我们使客户端能够进行如下查询:

mutation WritePost($body: String!){
  writePost(body: $body) {
    id
    posts {
      id
      body
    }
  }
}

这里 Apollo 不仅会为所有返回的帖子创建或更新缓存,还会更新返回的 User 对象,包括帖子列表。

那么为什么不经常这样做呢?为什么 Apollo 的文档建议在添加或删除节点时使用writeQuery

当您的架构很简单并且您使用的数据量相对较少时,上述方法可以正常工作。但是,一旦您处理更多数据,返回整个父节点(包括其所有关系)可能会明显变慢且资源密集。此外,在许多应用程序中,单个突变可能会影响缓存中的多个查询。同一个节点可以由模式中的任意数量的字段返回,甚至同一个字段也可能是使用不同过滤器、排序参数等的许多不同查询的一部分。

这些因素使您不太可能希望在生产中实现此模式,但肯定有一些用例可能是一个有效的选项。

【讨论】:

  • 感谢“为什么”部分 - 非常有用!
猜你喜欢
  • 2019-11-26
  • 2020-05-09
  • 2020-05-11
  • 2022-11-11
  • 2022-08-15
  • 1970-01-01
  • 2020-02-03
  • 2021-01-13
  • 2021-03-11
相关资源
最近更新 更多