Apollo Client中useQuery调用fetchMore触发两次网络请求如何解决?
修复方案
导致fetchMore触发两次请求的核心原因是Apollo Client判断原查询(offset=0、limit=12)的缓存数据与请求参数不匹配,因此在fetchMore完成后自动重新发起了初始查询,可通过以下步骤修复:
1. 调整useQuery的fetch策略
将nextFetchPolicy从cache-first改为cache-only,确保初始查询完成后,useQuery不会自动发起任何网络请求,仅从缓存读取数据:
const { data, fetchMore } = useQuery(GET_PODCAST_SERIES, { variables: { limit: 12, offset: 0, pathOrId: `${site}/podcast/${slug}`, }, // 初始查询用默认的cache-first,后续仅从缓存取数 nextFetchPolicy: 'cache-only', });
2. 补全fetchMore的入参
显式传入所有查询变量,避免不同版本Apollo Client的变量继承逻辑异常:
<button onClick={() => { fetchMore({ variables: { offset: length, limit: 12, pathOrId: `${site}/podcast/${slug}`, } }) }}>load more</button>
3. 完善缓存合并策略
补充PodcastSeriesQuery下的podcastSeries字段配置,忽略limit、offset参数对缓存键的影响,同时给列表合并增加去重逻辑避免重复数据:
cache: new InMemoryCache({ typePolicies: { Query: { fields: { PodcastSeriesQuery: { keyArgs: ['pathOrId'], merge(existing = {}, incoming) { return { ...existing, ...incoming }; }, }, }, }, // 新增PodcastSeriesQuery的字段策略 PodcastSeriesQuery: { fields: { podcastSeries: { // 不将limit、offset作为缓存键的组成部分 keyArgs: false } } }, PodcastSeries: { fields: { podcastEpisodes: { merge(existing = [], incoming) { // 新增去重逻辑,避免多次请求返回重复条目 const existIds = new Set(existing.map(item => item.id)); const validIncoming = incoming.filter(item => !existIds.has(item.id)); return [...existing, ...validIncoming]; }, }, }, }, }, }),
可选校验项
如果调整后问题仍然存在,检查组件是否存在意外重渲染逻辑,比如site、slug变量在fetchMore后发生变化,导致useQuery的variables变动触发重新查询。
内容的提问来源于stack exchange,提问作者Jamen
相关产品推荐
相关产品推荐

