Next.js中Apollo Client fetchMore无法更新数据缓存求助
问题分析与解决方案
1. 先确认后端数据一致性
手动在GraphQL Playground执行创建对话的mutation,紧接着执行GET_CONVERSATION_LIST查询:
- 如果新对话不在查询结果里,优先排查后端NestJS代码:
- 检查mutation是否正确提交数据库事务(比如TypeORM事务未完成就返回);
- 确认列表查询resolver是否存在缓存未更新的情况。
2. 修正Apollo Client的SSR模式配置
当前代码固定ssrMode: true,客户端运行时会导致缓存行为异常,需根据环境自动切换:
function createApolloClient() { return new ApolloClient({ ssrMode: typeof window === 'undefined', // 服务器端为true,客户端自动设为false link: createIsomorphLink(), cache: new InMemoryCache() }) }
3. 优化fetchMore的缓存更新逻辑
直接返回fetchMoreResult会完全覆盖旧数据,建议合并新旧数据并去重,确保缓存正确更新:
fetchMore({ context: { headers: { authorization: `Bearer ${getCookie("session")}` } }, updateQuery(prevResult, { fetchMoreResult }) { if (!fetchMoreResult) return prevResult; // 替换为你实际的列表字段名 const existingIds = prevResult.conversations.map(c => c.id); return { ...prevResult, conversations: [ ...fetchMoreResult.conversations, ...prevResult.conversations.filter(c => !existingIds.includes(c.id)) ] }; } })
4. 验证服务器端getServerSideProps查询正确性
在服务器端打印查询结果,确认是否能获取到新对话:
export const getServerSideProps: GetServerSideProps = async (ctx) => { const apolloClient = initializeApollo() const result = await apolloClient.query({ query: GET_CONVERSATION_LIST, context: { headers: { authorization: `Bearer ${ctx.req.cookies["session"]}` } }, errorPolicy: "all" }) // 打印结果排查问题 console.log("Server-side conversation data:", result.data); return { props: { initialApolloState: apolloClient.cache.extract(), } } }
- 如果服务器端查不到新数据,检查:
ctx.req.cookies["session"]是否与客户端创建对话时的会话一致;- 后端是否存在会话隔离或权限问题。
5. 修复Apollo缓存合并逻辑
使用深度合并(需安装lodash.merge)避免浅合并导致数据丢失:
import merge from 'lodash/merge'; export function initializeApollo(initialState = null) { const _apolloClient = apolloClient ?? createApolloClient() if (initialState) { const existingCache = _apolloClient.extract() const mergedData = merge({}, existingCache, initialState) _apolloClient.cache.restore(mergedData) } if (!apolloClient) apolloClient = _apolloClient return _apolloClient }
6. 可选:调整useQuery的fetchPolicy
如果需要强制客户端每次从服务器拉取最新数据(会影响SSR性能,按需使用):
const { data } = useQuery<GetConversationData>(GET_CONVERSATION_LIST, { fetchPolicy: "network-only" });
内容的提问来源于stack exchange,提问作者Keya Roy
相关产品推荐
相关产品推荐

