Apollo Client如何重新获取非活跃查询 解决新增列表后缓存刷新问题
Apollo 分页列表新增条目后缓存更新解决方案
方案1:使用mutation的update回调直接修改缓存(最推荐)
这是性能最优、最符合Apollo设计规范的实现方式,不需要触发额外请求,也不依赖列表查询是否处于活跃状态:
- 在定义新增条目的mutation时,配置
update回调 - 回调内通过
cache.readQuery读取现有列表的缓存数据,注意传入的查询参数要和发起列表查询时的参数完全一致 - 将mutation返回的新条目插入到缓存列表的对应位置(通常是第一页开头)
- 调用
cache.writeQuery把更新后的列表写回缓存 - 后续重定向到列表页时,
cache-first策略会直接读取更新后的缓存,不会出现旧数据闪烁问题
示例代码结构:
const [addItem] = useMutation(ADD_ITEM_MUTATION, { update(cache, { data: { addItem } }) { const { listData } = cache.readQuery({ query: GET_LIST_QUERY, variables: { page: 1, pageSize: 10 } }) cache.writeQuery({ query: GET_LIST_QUERY, variables: { page: 1, pageSize: 10 }, data: { listData: [addItem, ...listData] } }) } })
方案2:用状态标记位控制列表页主动重取
如果不想手动操作缓存,可以用轻量状态标记控制更新时机:
- 声明一个全局可访问的标记,比如用Apollo Reactive Variable、React Context或者本地存储都可以,初始值为
false - 新增条目mutation执行成功后,将标记设为
true,再执行重定向 - 列表组件内增加useEffect逻辑:组件挂载时如果标记为
true,就调用查询返回的refetch方法主动拉取最新数据,拉取完成后把标记改回false
方案3:延迟触发refetchQueries到路由跳转完成
如果你希望继续用refetchQueries能力,只需要调整它的执行时机即可:
- 不要把refetchQueries配置在mutation的参数里
- mutation执行成功后先触发路由跳转,等待路由跳转的异步回调完成后,再手动调用Apollo Client实例的
refetchQueries方法:
addItem().then(async () => { // 不同路由库等待跳转完成的写法不同,比如React Router v6可以直接等待navigate返回的promise await navigate('/list') // 此时列表组件已经挂载,查询处于活跃状态,refetch生效 await client.refetchQueries({ include: [GET_LIST_QUERY] }) })
以上三个方案都不需要切换到network-only策略,也不需要自行实现复杂的全量状态管理,可根据自身业务复杂度选择。
内容的提问来源于stack exchange,提问作者Gergő Horváth
相关产品推荐
相关产品推荐

