reactjs - 为什么需要 refetchQueries?
问题描述
我正在关注关于 GraphQL 的教程,在视频中,作者没有将 refetchQueries 用于 deleteMutation,并且所有的 UI 更新和突变都可以正常工作。但是这里的项目沙箱代码已更新,refetchQuery 现在用于 Job 组件上的此操作 -> 第 20 行 -> deleteJob(): codeSandBox。
我在我的应用程序中遇到了类似的问题,它不会自动更新 UI,而无需在任何地方完成 refetchQueries。如果我理解正确的话,Apollo 不应该通过 apollo-cache-inmemory 自动应用 Apollo 的缓存,在这种突变中执行突变和更新 UI。
开箱即用的 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 内部的样子):
{
"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 现在从如下所示的更新突变中获得答案:
{
"data": {
"updateJob": {
"__typename": "Job",
"id": 2,
"company": "Big Corp",
"title": "GraphQL Unicorn"
}
}
}
它可以使用该dataIdFromObject
函数来了解该对象属于"Job:2"
我们规范化缓存中的缓存键。Apollo 可以假设此版本比旧版本更新,并根据较新结果的偏好合并密钥。我们的缓存现在看起来像这样:
{
"Query": {
"jobs": ["Job:1", "Job:2"],
},
"Job:1": { ... },
"Job:2": {
"__typename": "Job",
"id": 2,
"company": "Big Corp",
"title": "GraphQL Unicorn" // updated!
}
}
然后"jobs"
查询将使用新作业自动更新,因为它只是引用作业而不存储实体本身。伟大的!但现在比较删除函数的结果:
{
"data": {
"deleteJob": {
"returning": {
"id": 2,
}
}
}
}
这个查询的结果可以是任何东西。Apollo 无法知道您刚刚删除了具有特定 id 的作业。也许如果 GraphQL 在规范中有一些东西,比如神奇的“__isDeleted”,我们会得到类似的东西:
{
"data": {
"deleteJob": {
"__typename": "Job",
"__isDeleted": true,
"id": 2,
}
}
}
}
我们可以给我们的缓存实现一个提示,即__isDeleted: true
应该从所有引用查询中删除实体。但不幸的是,这并不存在。不过这还不错,我们可以使用refetchQuery
触发另一个查询的重新获取,或者我们可以手动更新另一个查询:
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 });
}
});
推荐阅读
- swift - XCUITest 等待未经测试的应用程序达到空闲状态
- c# - asp.net 5 GC 需要 10 秒
- node.js - 使用多个前端时如何正确配置 Amplify CI/CD 管道(前端构建缺少 aws-exports)?
- angular - 从另一个组件调用一个组件
- scala - scala强制转换不兼容类型而不会引发错误
- ios - SKDownload 的 contentURL 不是 nil 但不存在
- reactjs - 为什么 React Vertical Graph Tree 中的第一个方向没有显示?
- vue.js - 无效的道具:道具“值”的自定义验证器检查失败
- kibana - 如果有人正在更改/创建报告,是否可以触发警报
- python - 在 nlargest 数据框中只找到一个值