Reactjs 如何在多个视图中处理变异后的缓存更新?

Reactjs 如何在多个视图中处理变异后的缓存更新?,reactjs,apollo,react-apollo,apollo-client,Reactjs,Apollo,React Apollo,Apollo Client,这是一个开放的问题,但希望它不会被删除 我使用的是react和apollo,尽管问题更一般 假设我的应用程序中有3个不同的视图,都使用相似(但不相同)的数据。 它们都使用单独的查询,但每个查询都使用公共操作,但返回的数据略有不同 假设我在某个地方有一个突变,它向数据中添加了一些东西(想象一下一个项目列表和一个新项目被添加) 比如说,在变异之后,我想更新缓存以反映这种变化。我正在使用读/写工具进行更新。 使用此设置,我需要更新3个查询-这将成为维护的噩梦 经过一番阅读,我觉得我做错了——我现在创建

这是一个开放的问题,但希望它不会被删除

我使用的是react和apollo,尽管问题更一般

假设我的应用程序中有3个不同的视图,都使用相似(但不相同)的数据。 它们都使用单独的查询,但每个查询都使用公共操作,但返回的数据略有不同

假设我在某个地方有一个突变,它向数据中添加了一些东西(想象一下一个项目列表和一个新项目被添加)

比如说,在变异之后,我想更新缓存以反映这种变化。我正在使用读/写工具进行更新。 使用此设置,我需要更新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
创建一篇文章

如果不使用
refetchquerys
或手动更新每个查询,如何使用这些突变创建或发布帖子并更新所有3个缓存查询?
我认为真正的问题是,这些查询中的每一个都单独存储在apollo in memory cache中。

听起来您已经研究并使用了更新参数,该参数可以传递给从UseMartation返回的变异函数。您可能正在使用proxy.readQuery和proxy.writeQuery来更新它(或者让这种神奇的事情在后台发生)。如果没有,这里是答案

另一种在概念上类似但更详细的方法是使用proxy.readFragment和proxy.writeFragment。您可以将类型上的一组属性指定为片段的一部分,并在出现新数据时更新该片段。很好的一点是,这个片段可以在任意数量的查询中使用,如果您更新片段,这些查询将更新


根据我的经验,这里是应该怎么做的


CreateDraftPost
突变的情况下:

  • 您调用该变异并传递一个
    update
    函数。在这个
    update
    函数中,您可以通过创建
    Post
    的新片段来修改根查询
    posts
    的缓存,然后将该片段添加到
    posts
    中。见此:
  • 由于
    PostTitles
    Posts
    都依赖于根查询
    Posts
    (只是在查询的字段中有所不同),并且您刚刚添加到
    Posts
    中的
    Post
    的新片段有足够的字段,因此您的
    PostTitles
    Posts
    应该自动反映更改
  • 由于
    CreateDraftPost
    始终使用
    published
    创建草稿,因此默认值为
    false
    。您不需要更新与
    PublishedPosts
    query相关的任何内容

  • PublishPost
    突变的情况下:

  • 调用该变异,返回的结果是带有更新字段的
    Post
    id
    published
    )。通过Apollo GraphQL缓存机制,此
    Post
    (由
    id
    标识)将在涉及的任何查询中更新。见此:
  • 但是,您需要手动更新
    PublishedPost
    查询。通过在突变调用中提供
    update
    函数来实现这一点。在这个
    update
    函数中,您将首先
    PublishedPost
    readQuery
    ,从返回的数据中创建一个新的
    Post
    ,最后
    writeQuery
    将此Post添加到
    PublishedPost
    结果中。请参阅:

  • 使用
    refetchquerys
    如何:

    • CreateDraftPost
      突变的情况下,仅查询
      Posts
      就足够了(应该相应地更新
      PostTitles
      )由于
      Posts
      PostTitles
      都依赖于相同的根查询
      Posts
      Posts
      中的字段也涵盖了
      PostTitles
    • PublishPost
      突变的情况下,我更愿意重新提取
      PublishdPost
      查询,以避免做整个
      update
      的事情(因为我很懒,而且我认为重新提取一个查询不会花费太多)

    谢谢您的回答。是的,我用过读/写,我应该在问题中说清楚。然而,由于我在问题中解释的原因,这是有问题的——要么更新多个查询,要么创建一个查询,这两种解决方案似乎都不好。writeFragment的问题是它不可观察-它不会自动更新查询。是的,一个最小的可复制示例会有很大帮助。@DanieleRicci我添加了一个示例-如果需要更多信息,请告诉我谢谢您的回答。总的来说,我觉得我可以只使用一个查询,然后把所有的道具放在那里(这是w