GraphQL Mutation后更新Apollo本地缓存:读取无结果,求正确实现
Apollo缓存更新问题排查与修复
问题现状
执行CREATE_POST Mutation成功在数据库创建Post,但在update回调中调用cache.readQuery({ query: GET_POSTS })返回空值,无法完成本地缓存更新。
当前代码片段
Mutation与调用代码
const CREATE_POST = gql` mutation createPost($title: String!, $body: String!, $userId: Int!) { createPost(title: $title, body: $body, userId: $userId) { title body userId } } `; const [createPost] = useMutation(CREATE_POST); const variables = { title, body, userId: numbered }; console.log('variables', variables); createPost({ variables, update(cache) { const results = cache.readQuery({ query: GET_POSTS }); console.log(results); // cache.writeQuery({ // query: GET_POSTS, // data: { // posts: [...posts, variables], // }, // }); }, });
InMemoryCache配置
typePolicies: { Query: { fields: { posts: { keyArgs: ['limit'], merge: (existing, incoming) => { console.log('existing', existing); console.log('incoming', incoming); const result = [...(existing || []), ...incoming]; return result; }, }, }, }, }
问题分析
当前缓存更新实现不正确,核心问题如下:
readQuery未传入匹配变量:你的typePolicies中posts字段的keyArgs设为['limit'],意味着不同limit值的GET_POSTS查询会被缓存为不同条目。如果调用readQuery时未传入与之前执行GET_POSTS时完全一致的variables(比如{ limit: 10 }),会找不到对应缓存数据,返回undefined。- 未处理缓存为空的情况:如果
GET_POSTS从未被执行过,缓存中原本就没有posts数据,readQuery会返回undefined,后续展开...posts会直接报错。 - 写入缓存用错数据:注释的
writeQuery中用了variables(请求参数)而非Mutation返回的真实Post数据,这会导致缓存数据与数据库实际数据不一致。
修复方案
修改后的update回调代码
createPost({ variables, update(cache, { data }) { // 替换为你实际调用GET_POSTS时使用的变量 const queryVariables = { limit: 10 }; // 读取缓存,缓存为空时返回默认空数组 const { posts = [] } = cache.readQuery({ query: GET_POSTS, variables: queryVariables, }) || {}; // 获取Mutation返回的新Post数据 const newPost = data.createPost; // 写入更新后的缓存 cache.writeQuery({ query: GET_POSTS, variables: queryVariables, data: { posts: [...posts, newPost], }, }); }, });
额外注意事项
- 确保
CREATE_POSTMutation返回的字段与GET_POSTS查询返回的Post字段完全一致,否则缓存合并会出现数据缺失。 - 如果
GET_POSTS包含其他影响结果的参数(比如offset),需要将其加入typePolicies的keyArgs数组中,避免不同参数的查询缓存被错误合并。
内容的提问来源于stack exchange,提问作者tryingToBeBetter
相关产品推荐
相关产品推荐

