如何在多个视图中处理突变后的缓存更新?
How to handle cache update after mutation in multiple views?
这更像是一个悬而未决的问题,但希望它不会被删除。
虽然问题比较笼统,但我正在使用 React 和 apollo。
假设我的应用程序中有 3 个不同的视图,它们都使用相似(但不相同)的数据。
它们都使用单独的查询,但每个查询都使用共同的操作,但返回的数据略有不同。
假设我在某个地方有一个突变,它向数据添加了一些东西(想想一个项目列表和一个正在添加的新项目)。
假设在突变后我想更新缓存以反映该变化。我正在使用 read/writeQuery 进行更新。
使用此设置,我需要更新 3 个查询 - 这变成了维护噩梦。
经过一些阅读,我发现我做错了 - 我现在创建了一个查询 - 现在我只需要在突变后更新那个查询,我的所有视图都会自动更新。
然而,问题是这个查询现在必须下载所有 3 个视图组合所需的所有数据 - 感觉这是非常低效的,因为一些视图将获得他们永远不会使用的数据。
有更好的方法吗?
请注意,read/writeFragment
将不起作用,因为它们不会更新基础查询 - 例如检查此答案:
如果您需要更具体的示例,请在评论中告诉我。
总而言之,我认为在这个设置中我会更好地处理全局状态并一起避免 apollo 缓存 - 但是我觉得被骗了因为 apollo 承诺会解决状态问题:)
编辑
这是一个具体的例子:
假设我们的 graphql 模式定义如下:
type Post {
id: ID!
title: String!
body: String
published: Boolean!
}
type Query {
posts(published: Boolean): [Post!]!
}
type Mutation {
createDraft(body: String!, title: String!): Post
publish(id: Int!): Post
}
现在,我们在客户端创建了 3 个查询和 2 个变更
query PostTitles {
posts {
id
title
}
}
query Posts {
posts {
id
title
body
published
}
}
query PublishedPosts {
posts (published: true) {
id
title
body
published
}
}
mutation CreateDraftPost ($body: String!, $title: String!) {
createDraft(body: $body, title: $title) {
id
title
body
published
}
}
mutation PublishPost ($id:ID!) {
publish (id: $id) {
id
published
}
}
请注意 createDraft
使用默认 false
published
值创建 post。
如何在不使用 refetchQueries
或手动更新每个查询的情况下使用这些突变中的任何一个来创建或发布 post 并更新所有 3 个缓存查询?
我认为真正的问题是这些查询中的每一个都单独存储在 apollo 内存缓存中。
听起来您已经研究并使用了可以传递给从 useMutation 返回的突变函数的更新参数。您可能正在使用 proxy.readQuery 和 proxy.writeQuery 来更新它(或者让这种魔法在后台发生)。如果没有,这里是 documentation.
另一种概念相似但更详细的方法是使用 proxy.readFragment 和 proxy.writeFragment。您可以将类型的一组属性指定为片段的一部分,并在新数据进入时更新该片段。好的部分是该片段可以在任意数量的查询中使用,如果您更新片段,这些查询将会更新。
根据我的经验,应该是这样的。
在CreateDraftPost
突变的情况下:
- 您调用突变并传递
update
函数。在此 update
函数中,您通过创建 Post
的新片段修改根查询 posts
的缓存,然后将此片段添加到 posts
中。看到这个:https://www.apollographql.com/docs/react/data/mutations/#making-all-other-cache-updates
- 由于
PostTitles
和 Posts
都依赖于根查询 posts
(只是查询字段不同)和 Post
的新片段刚添加到 posts
中的字段足够,您的 PostTitles
和 Posts
应该会自动反映更改。
- 因为
CreateDraftPost
始终创建草稿 published
默认为 false
。您不需要更新与 PublishedPosts
查询相关的任何内容。
在PublishPost
突变的情况下:
- 您调用突变,返回的结果是
Post
,其中包含更新的字段(id
、published
)。通过 Apollo GraphQL 缓存机制,这个 Post
(由 id
标识)将在它涉及的任何查询中更新。看到这个:https://www.apollographql.com/docs/react/data/mutations/#updating-a-single-existing-entity
- 但是,您需要手动更新
PublishedPost
查询。通过在变异调用中提供 update
函数来做到这一点。在这个 update
函数中,您将首先 readQuery
of PublishedPost
,从返回的数据中创建一个新的 Post
,最后 writeQuery
添加这个 post 进入 PublishedPost
结果。参考这个:https://www.apollographql.com/docs/react/caching/cache-interaction/#combining-reads-and-writes
如何使用refetchQueries
:
- 在
CreateDraftPost
突变的情况下,仅重新获取 Posts
查询应该就足够了(PostTitles
应该相应地更新),因为 Posts
和 PostTitles
依赖于相同的根查询 posts
并且 Posts
中的字段也覆盖了 PostTitles
中的字段
- 在
PublishPost
突变的情况下,我宁愿重新获取 PublishedPost
查询以避免做整个 update
事情(因为我很懒,我认为它不会重新获取 1 个查询花费了我很多)
这更像是一个悬而未决的问题,但希望它不会被删除。
虽然问题比较笼统,但我正在使用 React 和 apollo。
假设我的应用程序中有 3 个不同的视图,它们都使用相似(但不相同)的数据。 它们都使用单独的查询,但每个查询都使用共同的操作,但返回的数据略有不同。
假设我在某个地方有一个突变,它向数据添加了一些东西(想想一个项目列表和一个正在添加的新项目)。
假设在突变后我想更新缓存以反映该变化。我正在使用 read/writeQuery 进行更新。 使用此设置,我需要更新 3 个查询 - 这变成了维护噩梦。
经过一些阅读,我发现我做错了 - 我现在创建了一个查询 - 现在我只需要在突变后更新那个查询,我的所有视图都会自动更新。 然而,问题是这个查询现在必须下载所有 3 个视图组合所需的所有数据 - 感觉这是非常低效的,因为一些视图将获得他们永远不会使用的数据。
有更好的方法吗?
请注意,read/writeFragment
将不起作用,因为它们不会更新基础查询 - 例如检查此答案:
如果您需要更具体的示例,请在评论中告诉我。
总而言之,我认为在这个设置中我会更好地处理全局状态并一起避免 apollo 缓存 - 但是我觉得被骗了因为 apollo 承诺会解决状态问题:)
编辑
这是一个具体的例子:
假设我们的 graphql 模式定义如下:
type Post {
id: ID!
title: String!
body: String
published: Boolean!
}
type Query {
posts(published: Boolean): [Post!]!
}
type Mutation {
createDraft(body: String!, title: String!): Post
publish(id: Int!): Post
}
现在,我们在客户端创建了 3 个查询和 2 个变更
query PostTitles {
posts {
id
title
}
}
query Posts {
posts {
id
title
body
published
}
}
query PublishedPosts {
posts (published: true) {
id
title
body
published
}
}
mutation CreateDraftPost ($body: String!, $title: String!) {
createDraft(body: $body, title: $title) {
id
title
body
published
}
}
mutation PublishPost ($id:ID!) {
publish (id: $id) {
id
published
}
}
请注意 createDraft
使用默认 false
published
值创建 post。
如何在不使用 refetchQueries
或手动更新每个查询的情况下使用这些突变中的任何一个来创建或发布 post 并更新所有 3 个缓存查询?
我认为真正的问题是这些查询中的每一个都单独存储在 apollo 内存缓存中。
听起来您已经研究并使用了可以传递给从 useMutation 返回的突变函数的更新参数。您可能正在使用 proxy.readQuery 和 proxy.writeQuery 来更新它(或者让这种魔法在后台发生)。如果没有,这里是 documentation.
另一种概念相似但更详细的方法是使用 proxy.readFragment 和 proxy.writeFragment。您可以将类型的一组属性指定为片段的一部分,并在新数据进入时更新该片段。好的部分是该片段可以在任意数量的查询中使用,如果您更新片段,这些查询将会更新。
根据我的经验,应该是这样的。
在CreateDraftPost
突变的情况下:
- 您调用突变并传递
update
函数。在此update
函数中,您通过创建Post
的新片段修改根查询posts
的缓存,然后将此片段添加到posts
中。看到这个:https://www.apollographql.com/docs/react/data/mutations/#making-all-other-cache-updates - 由于
PostTitles
和Posts
都依赖于根查询posts
(只是查询字段不同)和Post
的新片段刚添加到posts
中的字段足够,您的PostTitles
和Posts
应该会自动反映更改。 - 因为
CreateDraftPost
始终创建草稿published
默认为false
。您不需要更新与PublishedPosts
查询相关的任何内容。
在PublishPost
突变的情况下:
- 您调用突变,返回的结果是
Post
,其中包含更新的字段(id
、published
)。通过 Apollo GraphQL 缓存机制,这个Post
(由id
标识)将在它涉及的任何查询中更新。看到这个:https://www.apollographql.com/docs/react/data/mutations/#updating-a-single-existing-entity - 但是,您需要手动更新
PublishedPost
查询。通过在变异调用中提供update
函数来做到这一点。在这个update
函数中,您将首先readQuery
ofPublishedPost
,从返回的数据中创建一个新的Post
,最后writeQuery
添加这个 post 进入PublishedPost
结果。参考这个:https://www.apollographql.com/docs/react/caching/cache-interaction/#combining-reads-and-writes
如何使用refetchQueries
:
- 在
CreateDraftPost
突变的情况下,仅重新获取Posts
查询应该就足够了(PostTitles
应该相应地更新),因为Posts
和PostTitles
依赖于相同的根查询posts
并且Posts
中的字段也覆盖了PostTitles
中的字段
- 在
PublishPost
突变的情况下,我宁愿重新获取PublishedPost
查询以避免做整个update
事情(因为我很懒,我认为它不会重新获取 1 个查询花费了我很多)