reactjs - 删除带有突变的项目时如何正确修改Apollo缓存
问题描述
我不确定自己做错了什么,因为一切正常,但是每次运行DELETE_PHOTO
突变时都会收到这个讨厌的错误消息:
替换用户对象的照片字段时,缓存数据可能会丢失。
我有用户对象,其中包含照片列表:
email: "test@test.fi"
fullname: "Test user"
id: "5f058ca0bf08318028019059"
isAdmin: true
photos:
0:{"__ref":"Photo:5f44b37892f7b011ec491f25"}
1:{"__ref":"Photo:5f44b37a92f7b011ec491f26"}
2:{"__ref":"Photo:5f44b37d92f7b011ec491f27"}
3:{"__ref":"Photo:5f44b38192f7b011ec491f28"}
4:{"__ref":"Photo:5f44b38792f7b011ec491f2a"}
5:{"__ref":"Photo:5f44b38992f7b011ec491f2b"}
6:{"__ref":"Photo:5f44b38c92f7b011ec491f2c"}
7:{"__ref":"Photo:5f44b38e92f7b011ec491f2d"}
8:{"__ref":"Photo:5f44b39092f7b011ec491f2e"}
9:{"__ref":"Photo:5f44b39292f7b011ec491f2f"}
10:{"__ref":"Photo:5f44b39492f7b011ec491f30"}
11:{"__ref":"Photo:5f44b39892f7b011ec491f31"}
12:{"__ref":"Photo:5f44b39a92f7b011ec491f32"}
13:{"__ref":"Photo:5f44b39d92f7b011ec491f33"}
14:{"__ref":"Photo:5f44b3a092f7b011ec491f34"}
15:{"__ref":"Photo:5f44b3a492f7b011ec491f35"}
16:{"__ref":"Photo:5f44b3a792f7b011ec491f36"}
17:{"__ref":"Photo:5f44b3aa92f7b011ec491f37"}
18:{"__ref":"Photo:5f44b3ad92f7b011ec491f38"}
19:{"__ref":"Photo:5f44b3af92f7b011ec491f39"}
20:{"__ref":"Photo:5f44b3b292f7b011ec491f3a"}
21:{"__ref":"Photo:5f44b3b592f7b011ec491f3b"}
22:{"__ref":"Photo:5f44c5e192f7b011ec491f3c"}
23:{"__ref":"Photo:5f453f1e479a7649e8191a04"}
username: "admin"
每个照片对象都是这样的:
dateAdded: "1598337912783"
description: null
filename: "images/851ca650-e69e-11ea-bdf1-eb9595fbd23e"
id: "5f44b37892f7b011ec491f25"
mainUrl: "https://firebasestorage.googleapis.com/..."
name: "2013-07-27 12-25-40 1479 (Canon EOS 40D)"
originalFilename: "2013-07-27 12-25-40 1479 (Canon EOS 40D).jpg"
thumbFilename: "images/851ca651-e69e-11ea-bdf1-eb9595fbd23e"
thumbUrl: "https://firebasestorage.googleapis.com/..."
获取用户对象的查询是:
export const ME = gql`
query me {
me {
username,
email,
fullname,
isAdmin,
photos {
mainUrl,
thumbUrl,
filename,
thumbFilename,
originalFilename,
name,
description,
dateAdded,
id
},
id
}
}
`;
删除照片的突变是:
export const DELETE_PHOTO = gql`
mutation deletePhoto(
$id: ID!
) {
deletePhoto(
id: $id
) {
mainUrl,
thumbUrl,
filename,
thumbFilename,
originalFilename,
name,
description,
dateAdded,
id
}
}
`;
当我执行DELETE_PHOTO
查询时,我得到这个关于已删除照片的对象作为响应:
deletePhoto:
dateAdded: "1598337912783"
description: null
filename: "images/851ca650-e69e-11ea-bdf1-eb9595fbd23e"
id: "5f44b37892f7b011ec491f25"
mainUrl: "https://firebasestorage.googleapis.com/..."
name: "2013-07-27 12-25-40 1479 (Canon EOS 40D)"
originalFilename: "2013-07-27 12-25-40 1479 (Canon EOS 40D).jpg"
thumbFilename: "images/851ca651-e69e-11ea-bdf1-eb9595fbd23e"
thumbUrl: "https://firebasestorage.googleapis.com/..."
__typename: "Photo"
然后我使用以下代码通过从用户对象的照片数组中删除该项目来更新 Apollo 缓存:
const [deletePhotoFromDb] = useMutation(DELETE_PHOTO, {
update: (cache, response) => {
const existingCache = cache.readQuery({ query: ME });
if (existingCache) {
const idToDelete = response.data.deletePhoto.id;
const updatedPhotos = existingCache.me.photos.filter(p => p.id !== idToDelete);
const updatedCache = {
...existingCache,
me: {
...existingCache.me,
photos: updatedPhotos
}
};
cache.writeQuery({
query: ME,
data: updatedCache
});
}
}
});
更新缓存有效,因为照片将立即从 React 的 UI 中删除。如果不更新缓存,照片将不会从 UI 中删除。
那么,我做错了什么来获取有关丢失缓存的错误消息?
Cache data may be lost when replacing the photos field of a User object.
To address this problem (which is not a bug in Apollo Client), define a custom merge function for the User.photos field, so InMemoryCache can safely merge these objects:
existing: [{"__ref":"Photo:5f44b37a92f7b011ec491f26"},{"__ref":"Photo:5f44b37d92f7b011ec491f27"},{"__ref":"Photo:5f44b38192f7b011ec491f28"},{"__ref":"Photo:5f44b38792f7b011ec491f2a"},{"__ref":"Photo:5f44b38992f7b011ec491f2b"},{"__ref":"Photo:5f44b38c92f7b011ec491f2c"},{"__ref":"Photo:5f44b38e92f7b011ec491f2d"},{"__ref":"Photo:5f44b39092f7b011ec491f2e"},{"__ref":"Photo:5f44b39292f7b011ec491f2f"},{"__ref":"Photo:5f44b39492f7b011ec491f30"},{"__ref":"Photo:5f44b39892f7b011ec491f31"},{"__ref":"Photo:5f44b39a92f7b011ec491f32"},{"__ref":"Photo:5f44b39d92f7b011ec491f33"},{"__ref":"Photo:5f44b3a092f7b011ec491f34"},{"__ref":"Photo:5f44b3a492f7b011ec491f35"},{"__ref":"Photo:5f44b3a792f7b011ec491f36"},{"__ref":"Photo:5f44b3aa92f7b011ec491f37"},{"__ref":"Photo:5f44b3ad92f7b011ec491f38"},{"__ref":"Photo:5f44b3af92f7b011ec491f39"},{"__ref":"Photo:5f44b3b292f7b011ec491f3a"},{"__ref":"Photo:5f44b3b592f7b011ec491f3b"},{"__ref":"Photo:5f44c5e192f7b011ec491f3c"},{"__ref":"Photo:5f453f1e479a7649e8191a04"}]
incoming: [{"__ref":"Photo:5f44b37a92f7b011ec491f26"},{"__ref":"Photo:5f44b37d92f7b011ec491f27"},{"__ref":"Photo:5f44b38192f7b011ec491f28"},{"__ref":"Photo:5f44b38792f7b011ec491f2a"},{"__ref":"Photo:5f44b38992f7b011ec491f2b"},{"__ref":"Photo:5f44b38c92f7b011ec491f2c"},{"__ref":"Photo:5f44b38e92f7b011ec491f2d"},{"__ref":"Photo:5f44b39092f7b011ec491f2e"},{"__ref":"Photo:5f44b39292f7b011ec491f2f"},{"__ref":"Photo:5f44b39492f7b011ec491f30"},{"__ref":"Photo:5f44b39892f7b011ec491f31"},{"__ref":"Photo:5f44b39a92f7b011ec491f32"},{"__ref":"Photo:5f44b39d92f7b011ec491f33"},{"__ref":"Photo:5f44b3a092f7b011ec491f34"},{"__ref":"Photo:5f44b3a492f7b011ec491f35"},{"__ref":"Photo:5f44b3a792f7b011ec491f36"},{"__ref":"Photo:5f44b3aa92f7b011ec491f37"},{"__ref":"Photo:5f44b3ad92f7b011ec491f38"},{"__ref":"Photo:5f44b3af92f7b011ec491f39"},{"__ref":"Photo:5f44b3b292f7b011ec491f3a"},{"__ref":"Photo:5f44b3b592f7b011ec491f3b"},{"__ref":"Photo:5f44c5e192f7b011ec491f3c"}]
解决方案
感谢xadm为我指出正确的评论方向。
我用以下内容替换了空的 InMemoryCache 对象,并且不再有警告消息:
const cache = new InMemoryCache({
typePolicies: {
User: {
fields: {
photos: {
merge(existing = [], incoming: any[]) {
return [...incoming];
}
}
}
}
}
});
推荐阅读
- javascript - 将 Math.max 与类型化子数组一起使用
- ios - 在 ios swift 中的 Paytm 中获取“无效校验和”
- sql - 仅在多位整数的前半部分查找 2 列之间的匹配项
- coldfusion - ColdFusion 检查 cookie 何时过期
- laravel - 未在 Laravel 8 中加载引导程序
- reactjs - 在 React Native 中隐藏导航的标题
- excel - 确定VBA范围内错误数量的有效公式或代码
- android-studio - 将 PDF 文件上传到 Google Drive 文件夹并覆盖现有文件
- python - 向我的第二个电子邮件帐户发送电子邮件时出现 SMTP 错误
- numpy - Scipy - 线性总和分配 - 显示工作原理