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
相关产品推荐
相关产品推荐

