Apollo Client调用fetchMore时每次额外重复请求第一页数据问题
问题根因
重复请求第一页的问题由两个配置错误共同导致:
- 全局设置的
query.fetchPolicy: 'network-only'会被fetchMore方法默认继承。network-only策略不会自动将新拉取的分页数据和原有数据做缓存合并,每次fetchMore触发组件重渲染时,useQuery会因不读取缓存,直接使用初始变量(offset: 0, limit:10)重新发起第一页请求,之后才发起目标页码的请求。 loadNextPage方法用useCallback包裹时依赖数组为空,闭包中捕获的data永远是组件首次渲染的快照,后续数据更新后回调内拿到的仍是旧值,既会导致分页偏移量计算错误,也会触发Apollo内部的变量校验逻辑,额外触发初始查询重拉。
此外原代码中fetchMore仅传入offset变量,未显式传入limit,变量缺省也可能触发非预期的重查逻辑。
修复方案
1. 补全Apollo Client缓存合并配置
在InMemoryCache中为分页字段配置merge逻辑,明确不同参数下的列表拼接规则,避免不同页码的请求被判定为独立查询:
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ // 原有uri等配置保持不变 defaultOptions: { query: { fetchPolicy: 'network-only' } }, cache: new InMemoryCache({ typePolicies: { Query: { fields: { feed: { merge(existing = [], incoming, { args }) { const mergedList = existing.slice(0); // 按传入的offset位置插入新拉取的页数据 for (let i = 0; i < incoming.length; i++) { mergedList[args.offset + i] = incoming[i]; } return mergedList; } } } } } }) });
2. 修正组件内分页逻辑
补全useCallback依赖,为fetchMore单独指定fetchPolicy覆盖全局的network-only配置,同时显式补全分页变量:
const { loading, data, fetchMore } = useQuery(FEED_QUERY, { variables: { offset: 0, limit: 10, }, }); const loadNextPage = useCallback(() => { return fetchMore({ variables: { offset: data.feed.length, limit: 10, }, // 覆盖全局network-only策略,避免触发初始页重查 fetchPolicy: 'cache-first' }); }, [data, fetchMore]); // 渲染逻辑 <button onClick={loadNextPage} disabled={loading}>Load more</button>;
修复逻辑说明
- 字段级merge配置让Apollo明确分页数据的缓存规则,新拉取的页数据会自动拼接到现有列表后,不会因参数不同被识别为全新查询。
- fetchMore单独设置
cache-first策略后,拉取到的新数据会直接写入缓存触发视图更新,不会触发初始变量的网络重拉。 - 补全依赖数组后回调内始终能拿到最新的列表数据,分页偏移量计算准确,不会因闭包陈旧值触发异常请求。
内容的提问来源于stack exchange,提问作者Alexey Kachalov
相关产品推荐
相关产品推荐

