为什么需要 refetchQueries? [英] Why is refetchQueries needed?

查看:43
本文介绍了为什么需要 refetchQueries?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习有关 GraphQL 的教程,在视频中,作者没有使用 refetchQueries 进行 deleteMutation,并且所有这些都适用于 UI 更新和突变.但这里在项目沙箱代码更新和 refetchQuery 现在用于作业组件上的此操作 -> line 20 -> deleteJob(): codeSandBox.

I am following a tutorial on GraphQL, in the video the author does not use refetchQueries for a deleteMutation and all works well with UI updates and mutation. But here in the project sandbox code is updated and refetchQuery is now used for this operatio on Job component -> line 20 -> deleteJob(): codeSandBox.

我的应用程序中也有类似的问题,如果没有在任何地方完成 refetchQueries,它就不会自动更新 UI.Apollo不应该通过apollo-cache-inmemory自动应用Apollo的缓存,如果我理解正确的话,在这种突变中执行突变和更新UI.

I have this similar problem in my app that does not update the UI automatically without refetchQueries done everywhere. Shouldn't Apollo be applying automatically the cache of Apollo via apollo-cache-inmemory, perform mutation and update UI in this kind of mutation if I understand it right.

使用 apollo-boost 开箱即用的示例:

Example out of the box with apollo-boost:

export default gql`
mutation deleteItem($id: uuid!) {
  delete_item(where: {id:{_eq: $id }}){
    returning {
      id
    }
  }
}`;

 const onDeleteItem = (id) => {
    deleteItem({
      variables: { id },
    });
  };

对此有何建议或经验?

推荐答案

答案相对简单:GraphQL 中没有通用的方式来告诉客户端实体已被删除.让我们首先将其与更新突变进行比较.想象一下,我们正在更新缓存中已有的作业之一.首先是缓存(简化,实际上并不是它在 Apollo 内部的样子):

The answer is relatively simple: There is no universal way in GraphQL to tell a client that an entity was deleted. Let's first compare this to an update mutations. Imagine we are updating one of the jobs that we already have in our cache. First the cache (simplified, not actually quite how it looks inside of Apollo):

{
  "Query": {
    "jobs": ["Job:1", "Job:2"],
  },
  "Job:1": {
    "__typename": "Job",
    "id": 1,
    "company": "Big Corp",
    "title": "Sales Specialist"
  },
  "Job:2": {
    "__typename": "Job",
    "id": 2,
    "company": "Big Corp",
    "title": "GraphQL Expert"
  }
}

如果 Apollo 现在从如下所示的更新突变中得到答案:

If Apollo now gets an answer from an update mutation that looks like the following:

{
  "data": {
    "updateJob": {
      "__typename": "Job",
      "id": 2,
      "company": "Big Corp",
      "title": "GraphQL Unicorn"
    }
  }
}

它可以使用dataIdFromObject函数来了解对象属于我们规范化缓存中的缓存键"Job:2".Apollo 可以假设此版本比旧版本新,并根据较新结果的偏好合并密钥.我们的缓存现在看起来像这样:

It can use the dataIdFromObject function to understand that the object belongs to the cache key "Job:2" in our normalised cache. Apollo can assume that this version is newer than the old one and merge the keys with preference of the newer result. Our cache now looks like this:

{
  "Query": {
    "jobs": ["Job:1", "Job:2"],
  },
  "Job:1": { ... },
  "Job:2": {
    "__typename": "Job",
    "id": 2,
    "company": "Big Corp",
    "title": "GraphQL Unicorn" // updated!
  }
}

然后 "jobs" 查询将自动更新为新作业,因为它只是引用作业而不存储实体本身.伟大的!但是现在比较删除函数的结果:

Then the "jobs" query will automatically update with the new job because it is just referencing the job and is not storing the entity itself. Great! But now compare the result from the delete function:

{
  "data": {
    "deleteJob": {
      "returning": {
        "id": 2,
      }
    }
  }
}

这个查询的结果可以是任何东西.Apollo 无法知道您刚刚删除了具有特定 ID 的作业.也许如果 GraphQL 在规范中有一些像神奇的__isDeleted"这样的东西,我们会得到类似的东西:

The result of this query could be anything. Apollo cannot know that you have just deleted a job with a certain id. Maybe if GraphQL had something in the specification like a magical "__isDeleted" and we would get something like:

{
  "data": {
    "deleteJob": {
        "__typename": "Job",
        "__isDeleted": true,
        "id": 2,
      }
    }
  }
}

我们可以给我们的缓存实现一个提示,即应该从所有引用查询中删除带有 __isDeleted: true 的实体.但不幸的是,这并不存在.不过这还不错,我们可以使用 refetchQuery 来触发另一个查询的重新获取,或者我们可以 手动更新另一个查询:

We could give our cache implementation the hint that entities with __isDeleted: true should be removed from all referencing queries. But unfortunately this does not exists. This is not to bad though, we can either use refetchQuery to trigger a refetch of the other query or we can manually update the other query:

const deleteJob = useMutation(DELETE_JOB, {
  update(store, response) {
    const data = store.readQuery({ query: GET_JOBS });
    data.jobs = data.jobs.filter(job => job.id !== response.deleteJob.returning.id);
    store.writeQuery({ query: GET_JOBS, data });
  }
});

这篇关于为什么需要 refetchQueries?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆