首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在apollo-client中从客户端缓存中删除项目的正确方法

在apollo-client中从客户端缓存中删除项目的正确方法
EN

Stack Overflow用户
提问于 2020-07-30 13:36:36
回答 2查看 3.8K关注 0票数 7

我在我的React(Typescript)应用程序中使用带有内存缓存的GraphQL和Apollo-Client。缓存根据添加的新项进行更新,工作正常,不会出现错误。

当项目被删除时,从GraphQL Apollo服务器后端返回一个字符串,声明成功的删除操作,该操作启动要调用的更新函数,该函数读取缓存,然后通过过滤掉项目的id来修改它。这是使用来自Apollo-Client的突变钩子执行的。

代码语言:javascript
复制
const [deleteBook] = useMutation<{ deleteBook: string }, DeleteBookProps>(DELETE_BOOK_MUTATION, {
    variables: { id },
    onError(error) {
      console.log(error);
    },
    update(proxy) {
      const bookCache = proxy.readQuery<{ getBooks: IBook[] }>({ query: GET_BOOKS_QUERY });
      if (bookCache) {
        proxy.writeQuery<IGetBooks>({
          query: GET_BOOKS_QUERY,
          data: { getBooks: bookCache.getBooks.filter((b) => b._id !== id) },
        });
      }
    },
  });

该函数起作用,前端将使用缓存中的正确项进行更新,但控制台中会显示以下错误:

代码语言:javascript
复制
Cache data may be lost when replacing the getBooks field of a Query object.

To address this problem (which is not a bug in Apollo Client), define a custom merge function for the Query.getBooks field, so InMemoryCache can safely merge these objects:

  existing: [{"__ref":"Book:5f21280332de1d304485ae80"},{"__ref":"Book:5f212a1332de1d304485ae81"},{"__ref":"Book:5f212a6732de1d304485ae82"},{"__ref":"Book:5f212a9232de1d304485ae83"},{"__ref":"Book:5f21364832de1d304485ae84"},{"__ref":"Book:5f214e1932de1d304485ae85"},{"__ref":"Book:5f21595a32de1d304485ae88"},{"__ref":"Book:5f2166601f6a633ae482bae4"}]
  incoming: [{"__ref":"Book:5f212a1332de1d304485ae81"},{"__ref":"Book:5f212a6732de1d304485ae82"},{"__ref":"Book:5f212a9232de1d304485ae83"},{"__ref":"Book:5f21364832de1d304485ae84"},{"__ref":"Book:5f214e1932de1d304485ae85"},{"__ref":"Book:5f21595a32de1d304485ae88"},{"__ref":"Book:5f2166601f6a633ae482bae4"}]

For more information about these options, please refer to the documentation:

  * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers
  * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects

有没有更好的方法来更新缓存,这样就不会收到这个错误?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-30 14:50:48

我也面临着完全相同的警告,不幸的是,除了这里建议的解决方案之外,我没有想出其他的解决方案:https://go.apollo.dev/c/merging-non-normalized-objects

代码语言:javascript
复制
const client = new ApolloClient({
  ....
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          getBooks: {
            merge(existing, incoming) {
              return incoming;
            },
          },
        },
      },
    }
  }),
});

(我不确定我是否正确地编写了您的字段和类型,因此您可以稍微修改一下这段代码)

基本上,上面的代码让apollo客户端如何处理可合并的数据。在本例中,我只需用新数据替换旧数据。

我想知道有没有更好的解决方案

票数 7
EN

Stack Overflow用户

发布于 2021-03-11 17:41:30

我也遇到过同样的问题。我遇到了一个提供两种替代解决方案here的GitHub线程。

第一个是在调用cache.writeQuery之前清除缓存中的内容

代码语言:javascript
复制
  cache.evict({
    // Often cache.evict will take an options.id property, but that's not necessary
    // when evicting from the ROOT_QUERY object, as we're doing here.
    fieldName: "notifications",
    // No need to trigger a broadcast here, since writeQuery will take care of that.
    broadcast: false,
  });

简而言之,这将刷新您的缓存,因此您的新数据将成为新的真理来源。不用担心会丢失旧数据。

关于阿波罗客户端v3的另一个建议发布在下面的same thread

代码语言:javascript
复制
cache.modify({
  fields: {
    notifications(list, { readField }) {
      return list.filter((n) => readField('id', n) !==id)
    },
  },
})

这种方式消除了大量的样板文件,因此您不需要使用readQueryevictwriteQuery。问题是,如果你运行Typescript,你会遇到一些实现问题。在本质上,使用的格式是InMemoryCache格式,而不是通常的GraphQL数据。您将看到Reference对象、未推断的类型以及其他奇怪的东西。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63166812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档