Apollo Client跨Query更新缓存问题:新增Feed无法同步至Screen B
问题说明
在Screen A创建Feed后,以下代码可成功更新seeAllFeeds查询的缓存,对应界面能即时刷新:
const updateUploadPhoto = (cache, result) => { const { data: { createFeed }, } = result; if (createFeed.id) { cache.modify({ id: "ROOT_QUERY", fields: { seeAllFeeds(prev) { return [createFeed, ...prev]; }, }, }); } }
但Screen B使用的seeCertainUserFeedpoem查询无法同步新增Feed的信息,且受FlatList限制不能通过刷新解决(刷新会回到顶部)。
尝试两种方法均失败:
- 手动调用
cache.modify匹配seeCertainUserFeedpoem数据:
const updateUploadPhoto = (cache, result) => { const { data: { createFeed }, } = result; const FeedpomeId = `Feedpoem:${createFeed.id}`; const FeedpoemFragment = { caption: createFeed.caption, commentNumber: createFeed.commentNumber, createdAt: createFeed.createdAt, id: createFeed.id, isLiked: createFeed.isLiked, isMine: createFeed.isMine, likeNumber: createFeed.likeNumber, photos: createFeed.photos, poemCaption: null, poemCommentNumber: 0, poemLikeNumber: 0, poemTitle: null, updatedAt: createFeed.updatedAt, }; if (createFeed.id) { cache.modify({ id: "ROOT_QUERY", fields: { seeAllFeeds(prev) { return [createFeed, ...prev]; }, }, }); cache.modify({ id: FeedpomeId, data: FeedpoemFragment, }); navigation.navigate("Tabs", { screen: "일상" }); } };
- 使用
client.writeFragment时抛出错误:
LogBox.js:173 Possible Unhandled Promise Rejection (id: 0): Error: Cannot read properties of undefined (reading 'definitions') Error: Cannot read properties of undefined (reading 'definitions')
解决方案
方法1:同时更新ROOT_QUERY下的两个列表字段
需要在cache.modify中同时处理seeAllFeeds和seeCertainUserFeedpoem,并确保实体正确写入缓存:
import { gql } from '@apollo/client'; const updateUploadPhoto = (cache, result) => { const { data: { createFeed } } = result; if (!createFeed.id) return; // 同时更新两个查询的列表数据 cache.modify({ id: "ROOT_QUERY", fields: { seeAllFeeds(prev) { return [createFeed, ...prev]; }, // 处理特定用户的Feed列表 seeCertainUserFeedpoem(prev, { args }) { // 匹配当前创建Feed的用户ID(根据你的实际查询参数调整) if (args.userId === createFeed.userId) { return [createFeed, ...prev]; } return prev; } }, }); // 写入完整实体到缓存,确保后续查询能读取到 cache.writeFragment({ id: `Feedpoem:${createFeed.id}`, fragment: gql` fragment FeedpoemDetails on Feedpoem { caption commentNumber createdAt id isLiked isMine likeNumber photos poemCaption poemCommentNumber poemLikeNumber poemTitle updatedAt userId # 确保包含用户ID字段,用于匹配特定用户查询 } `, data: createFeed, }); navigation.navigate("Tabs", { screen: "일상" }); };
关键说明:
- 必须在
cache.modify中更新seeCertainUserFeedpoem字段,否则界面不会感知到列表新增项; writeFragment需要传入gql解析的片段,而非纯对象,这是之前报错的核心原因;- 需确保
createFeed包含userId(或匹配seeCertainUserFeedpoem查询参数的字段),用于判断是否需要更新该查询的列表。
方法2:直接写入特定查询结果
如果明确知道seeCertainUserFeedpoem的查询参数,可直接用writeQuery更新缓存:
import { gql } from '@apollo/client'; const updateUploadPhoto = (cache, result) => { const { data: { createFeed } } = result; if (!createFeed.id) return; // 更新seeAllFeeds cache.modify({ id: "ROOT_QUERY", fields: { seeAllFeeds(prev) { return [createFeed, ...prev]; }, }, }); // 写入特定用户的Feed查询结果 const targetUserId = createFeed.userId; const existingFeeds = cache.readQuery({ query: gql` query seeCertainUserFeedpoem($userId: ID!) { seeCertainUserFeedpoem(userId: $userId) { caption commentNumber createdAt id isLiked isMine likeNumber photos poemCaption poemCommentNumber poemLikeNumber poemTitle updatedAt } } `, variables: { userId: targetUserId } })?.seeCertainUserFeedpoem || []; cache.writeQuery({ query: gql` query seeCertainUserFeedpoem($userId: ID!) { seeCertainUserFeedpoem(userId: $userId) { caption commentNumber createdAt id isLiked isMine likeNumber photos poemCaption poemCommentNumber poemLikeNumber poemTitle updatedAt } } `, variables: { userId: targetUserId }, data: { seeCertainUserFeedpoem: [createFeed, ...existingFeeds] } }); navigation.navigate("Tabs", { screen: "일상" }); };
之前失败的原因分析
- 第一种方法:仅更新了实体数据,但未修改
ROOT_QUERY下的seeCertainUserFeedpoem列表字段,界面订阅的是该列表,因此不会更新; - 第二种方法:使用
writeFragment时未传入合法的gql片段(仅传了纯对象),导致Apollo Client内部无法解析片段定义,抛出definitions未定义的错误。
内容的提问来源于stack exchange,提问作者Hyejung
相关产品推荐
相关产品推荐

