如何让Apollo Client在mutation后重新获取所有alertsPage查询?
解决Apollo Client Mutation后重新获取所有参数变体的查询
方法1:函数式refetchQueries获取所有查询缓存变体
当你给refetchQueries传查询名称字符串时,Apollo Client只会重新获取最近执行的该名称查询实例。要覆盖所有参数变体的查询,改用函数形式,手动从缓存中提取所有alertsPage的查询记录:
export function useCloseAlert() { const client = useApolloClient(); return useMutation(closeAlertDocument, { refetchQueries: async () => { // 筛选缓存中所有属于alertsPage查询的键 const alertQueryKeys = Object.keys(client.cache.data.data).filter(key => key.startsWith('Query.alertsPage(') ); // 将每个缓存键转换为包含变量的查询对象 return alertQueryKeys.map(key => { // 解析缓存键中的变量参数 const variables = JSON.parse(key.split('(')[1].slice(0, -1)); return { query: alertsPageDocument, variables, }; }); }, }); }
方法2:直接更新缓存替代重新请求
如果不想发起额外网络请求,可以在update函数中手动修改缓存里的统计数据,比如关闭告警后调整OPEN/CLOSED的计数:
export function useCloseAlert() { const client = useApolloClient(); return useMutation(closeAlertDocument, { update(cache, { data }) { if (!data?.closeAlert) return; // 遍历所有alertsPage查询缓存 const alertQueryKeys = Object.keys(cache.data.data).filter(key => key.startsWith('Query.alertsPage(') ); alertQueryKeys.forEach(key => { const variables = JSON.parse(key.split('(')[1].slice(0, -1)); const existingData = cache.readQuery({ query: alertsPageDocument, variables }); if (existingData?.alerts?.counts) { // 更新计数:OPEN减1,CLOSED加1 const updatedCounts = existingData.alerts.counts.map(count => { switch(count.status) { case 'OPEN': return { ...count, count: count.count - 1 }; case 'CLOSED': return { ...count, count: count.count + 1 }; default: return count; } }); // 写回缓存 cache.writeQuery({ query: alertsPageDocument, variables, data: { ...existingData, alerts: { ...existingData.alerts, counts: updatedCounts } } }); } }); }, }); }
方法3:重新获取活跃的查询实例(Apollo Client 3+)
如果只需要重新获取当前活跃的(比如页面正在监听的)alertsPage查询,可以通过查询管理器获取:
export function useCloseAlert() { const client = useApolloClient(); return useMutation(closeAlertDocument, { refetchQueries: () => { // 筛选所有活跃的alertsPage查询 return client.queryManager.getObservableQueries() .filter(query => query.options.query.definitions[0].name.value === 'alertsPage') .map(query => ({ query: query.options.query, variables: query.options.variables })); }, }); }
各方法对比
- 方法1:重新发起所有查询,数据绝对最新,但会增加网络请求量。
- 方法2:无网络开销,性能更好,但需要手动维护缓存更新逻辑,适合简单数据变更场景。
- 方法3:仅更新活跃查询,适合不需要同步历史缓存的场景。
内容的提问来源于stack exchange,提问作者Naresh
相关产品推荐
相关产品推荐

