突变后自动更新 apollo 客户端缓存,不影响现有查询

apo*_*kul 1 graphql react-apollo apollo-client

我有一个突变(UploadTransaction)返回某个名为 Transaction 的对象的特定列表。

#import "TransactionFields.gql" 
mutation UploadTransaction($files: [Upload!]!) {
  uploadFile(files: $files){
    transactions {
      ...TransactionFields
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

从后端(石墨烯)返回的交易具有 id 和 typename 字段。因此它应该自动更新缓存中的事务。在 Apollo 的 chrome 开发工具中,我可以看到新的交易:

在此处输入图片说明

我还有一个查询 GetTransactions 获取所有 Transaction 对象。

#import "TransactionFields.gql"
query GetTransactions {
  transactions {
    ...TransactionFields
  }
}
Run Code Online (Sandbox Code Playgroud)

但是我没有看到查询返回新添加的事务。在初始加载期间,Apollo 客户端加载了 292 个事务,显示在 ROOT_QUERY 下。它不断返回相同的 292 笔交易。UploadTransaction 突变在开发工具的缓存中添加“事务”类型的新对象,而不会影响开发工具中的 ROOT_QUERY 或我在代码中的查询。

在此处输入图片说明

TransactionFields.gql 是

fragment TransactionFields on Transaction {
    id
    timestamp
    description
    amount
    category {
      id
      name
    }
    currency
}
Run Code Online (Sandbox Code Playgroud)

知道我做错了什么吗?我是阿波罗客户端和 graphql 的新手

Dan*_*den 7

文档

如果突变更新了单个现有实体,则 Apollo 客户端可以在突变返回时自动更新其缓存中该实体的值。为此,变更必须返回修改实体的 id,以及修改字段的值。方便的是,默认情况下,Apollo Client 中的突变会执行此操作...

如果突变修改了多个实体,或者创建或删除了实体,则 Apollo 客户端缓存不会自动更新以反映突变的结果。为了解决这个问题,您对 useMutation 的调用可以包含一个更新函数。

如果您有一个返回实体列表(例如,用户)的查询,然后创建或删除用户,Apollo 无法知道应该更新列表以反映您的变更。原因有二

  • 有没有办法让阿波罗知道什么突变实际上是做什么。它只知道您正在请求哪些字段以及您传递这些字段的参数是什么。我们可能会假设包含“插入”或“创建”等词的突变是在后端插入一些东西,但这不是给定的。
  • 没有办法知道插入、删除或更新用户应该更新特定查询。您的查询可能针对名为“Bob”的所有用户——如果您创建名为“Susan”的用户,则不应更新查询以反映该添加。类似地,如果突变更新了用户,则可能需要更新查询以反映更改。它是否应该最终归结为只有您的服务器知道的业务规则。

因此,为了更新缓存,您有两个选择:

  • 触发相关查询的重新获取。您可以通过refetchQueriesuseMutation钩子传递选项或手动调用refetch这些查询来完成此操作。由于这需要向您的服务器发送一个或多个额外请求,因此它是较慢且成本较高的选项,但在 A) 您不想将一堆业务逻辑注入客户端或 B) 更新到缓存复杂而广泛。
  • update您的useMutation钩子提供一个函数,告诉 Apollo如何根据突变的结果更新缓存。这使您免于发出任何其他请求,但确实意味着您必须在服务器和客户端之间复制一些业务逻辑。

update来自文档的使用示例:

update (cache, { data: { addTodo } }) {
  const { todos } = cache.readQuery({ query: GET_TODOS });
  cache.writeQuery({
    query: GET_TODOS,
    data: { todos: todos.concat([addTodo]) },
  });
}
Run Code Online (Sandbox Code Playgroud)

阅读文档以获取更多详细信息。