You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js + @apollo/client服务端数据获取数据重复问题求助

解决Next.js + Apollo Client页面返回后数据重复问题

问题分析

数据重复的核心原因在于:Apollo缓存未针对你的查询字段配置正确的数组合并规则,加上缓存合并逻辑的去重处理不足,导致服务端与客户端缓存数据叠加重复。

解决方案

1. 为目标查询字段配置缓存合并规则

在apolloClient.ts的InMemoryCache配置中,将默认的allPosts替换为你GET_SECTION_LIST查询返回的根字段名(比如实际字段是sectionList,请根据你的GraphQL返回结构修改),让Apollo知道如何正确合并数组数据:

cache: new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        // 替换为你查询返回的实际字段名
        sectionList: concatPagination(),
      },
    },
  },
}),

concatPagination()会自动处理数组的分页与合并逻辑,避免无意义的重复追加。

2. 优化缓存合并的去重逻辑

修改initializeApollo函数中的arrayMerge逻辑,改用Map实现更可靠的数组去重:

const data = merge(existingCache, initialState, {
  arrayMerge: (destinationArray, sourceArray) => {
    const uniqueItems = new Map();
    // 先保留客户端已有缓存
    destinationArray.forEach(item => uniqueItems.set(JSON.stringify(item), item));
    // 覆盖添加服务端缓存数据,自动去重
    sourceArray.forEach(item => uniqueItems.set(JSON.stringify(item), item));
    return Array.from(uniqueItems.values());
  },
}),

原来的基于isEqual的去重逻辑在复杂对象场景下可能失效,JSON字符串作为键的Map可以更稳定地判断元素唯一性。

3. 明确useQuery的缓存策略

在list.tsx的useQuery中指定缓存策略,避免不必要的重复请求或缓存读取:

const { data, error } = useQuery<GetSectionListData>(GET_SECTION_LIST, {
  variables: { searchInput: {} },
  // 服务端已预取数据,优先读取缓存
  fetchPolicy: 'cache-first',
});

如果需要每次返回页面都验证缓存有效性,可以改用cache-and-network,但需确保已完成上述缓存去重配置。

4. 验证服务端缓存传递

确认getServerSideProps中已正确执行查询并传递缓存:

  • 检查addApolloState是否将服务端缓存正确注入到pageProps
  • 客户端useQuery会自动读取服务端预存的缓存,无需重复发起请求

内容的提问来源于stack exchange,提问作者Savana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 01:13:24