为什么需要refetchQueries?

时间:2019-10-30 21:26:38

标签: reactjs graphql apollo apollo-client

我正在关注有关GraphQL的教程,在视频中,作者没有使用refetchQueries进行deleteMutation,并且都可以很好地与UI更新和变异一起使用。但是在这里,项目沙箱中的代码已更新,现在refetchQuery用于Job组件->第20行-> deleteJob():codeSandBox上的此操作。

我的应用程序中存在类似的问题,如果没有在任何地方进行refetchQueries都不会自动更新UI。如果我理解正确的话,Apollo不应通过apollo-cache-memory自动应用Apollo的缓存,执行突变并以这种突变方式更新UI。

带有阿波罗升压功能的开箱即用示例:

export default gql`
mutation deleteItem($id: uuid!) {
  delete_item(where: {id:{_eq: $id }}){
    returning {
      id
    }
  }
}`;
 const onDeleteItem = (id) => {
    deleteItem({
      variables: { id },
    });
  };

对此有任何建议或经验吗?

1 个答案:

答案 0 :(得分:2)

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

$ es61 /orthography
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /orthography
es61: /orthography is not a valid directory
Process 64463 exited with normal status 0x0100 (status 1 = 0x01)
$ es61 $PWD
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /Users/jonathanleffler/soq
total 1016
drwxr-xr-x  100 jonathanleffler  staff   3200 Oct 31 15:53 .
drwxr-xr-x+  69 jonathanleffler  staff   2208 Oct 31 15:53 ..
…
-rwxr-xr-x    1 jonathanleffler  staff   9028 Oct 31 15:53 es61
-rw-r--r--    1 jonathanleffler  staff   1806 Oct 31 15:53 es61.c
drwxr-xr-x    3 jonathanleffler  staff     96 Oct 31 15:43 es61.dSYM
drwxr-xr-x    9 jonathanleffler  staff    288 Nov  5  2018 etc
…
-rw-r--r--    1 jonathanleffler  staff    390 Nov 16  2017 makefile
…
Process 64557 exited with normal status 0x0000 (status 0 = 0x00)
$

如果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"
  }
}

它可以使用{ "data": { "updateJob": { "__typename": "Job", "id": 2, "company": "Big Corp", "title": "GraphQL Unicorn" } } } 函数来了解该对象属于我们规范化缓存中的缓存键dataIdFromObject。 Apollo可以假定此版本比旧版本新,并以优先于较新结果的方式合并密钥。现在,我们的缓存如下所示:

"Job:2"

然后{ "Query": { "jobs": ["Job:1", "Job:2"], }, "Job:1": { ... }, "Job:2": { "__typename": "Job", "id": 2, "company": "Big Corp", "title": "GraphQL Unicorn" // updated! } } 查询将自动使用新作业进行更新,因为它只是引用作业,而不是存储实体本身。大!但是现在比较删除功能的结果:

"jobs"

此查询的结果可以是任何值。阿波罗不知道您刚刚删除了具有特定ID的作业。也许GraphQL在规范中包含神奇的“ __isDeleted”之类的东西,我们会得到类似的东西:

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

我们可以给我们的缓存实现一个提示,即应从所有引用查询中删除带有{ "data": { "deleteJob": { "__typename": "Job", "__isDeleted": true, "id": 2, } } } } 的实体。但是不幸的是这并不存在。不过,这还不错,我们可以使用__isDeleted: true来触发其他查询的重新提取,也可以manually update the other query

refetchQuery