Apollo Client fetchMore缓存已更新,但useQuery返回数据未更新
问题分析与解决方案
核心问题
你设置的fetchPolicy: 'network-only'是导致useQuery返回的data不更新的关键原因。这个策略会强制useQuery始终从网络获取初始的第一页数据,完全绕过缓存——即使你已经通过fetchMore将新数据合并到缓存中,组件也不会读取缓存里的合并结果。
修复步骤
1. 修改查询的获取策略
将useQuery的fetchPolicy改为cache-and-network或cache-first:
cache-and-network:首次加载时同时请求网络和读取缓存(若存在),后续缓存更新会立即触发组件渲染,同时后台会同步更新缓存(适合需要数据相对实时的场景)。cache-first:优先从缓存读取数据,仅当缓存无对应数据时才发起网络请求(适合分页数据不需要实时刷新的场景)。
修改后的useQuery代码:
const { loading, data, fetchMore, refetch, variables: originalVariables } = useQuery<PostsQuery>(ALL_POSTS_QUERY, { variables: { input: { type: PostType.SOMETHING, }, }, fetchPolicy: 'cache-and-network', // 替换原有的network-only notifyOnNetworkStatusChange: true, });
2. 合并主查询的变量到fetchMore请求中
你的主查询包含type: PostType.SOMETHING参数,fetchMore时如果只传递startKey,可能导致服务器返回不符合筛选条件的数据。需要将主查询的变量与分页变量合并:
const fetchMorePostsHandler = async () => { if (!postsLastKey) { return; } await fetchMore({ variables: { input: { ...originalVariables.input, // 继承主查询的筛选参数 startKey: postsLastKey, }, }, }); }, [postsLastKey, fetchMore, originalVariables]);
3. 验证merge函数的正确性
确认fetchMore返回的incoming数据结构与你的合并逻辑匹配。如果你的ALL_POSTS_QUERY返回结构为{ posts: Post[] },当前的merge逻辑是正确的;若返回结构不同,需调整incoming的取值路径。
原理说明
当使用缓存相关的fetchPolicy时,Apollo Client会监听缓存中Query.posts字段的变化。fetchMore执行后,merge函数将新数据合并到缓存,Apollo会自动通知useQuery订阅的组件,使其获取更新后的缓存数据并重新渲染。
内容的提问来源于stack exchange,提问作者Stephen Fong
相关产品推荐
相关产品推荐

