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

GraphQL执行mutation后如何更新subscription对应缓存解决更新延迟?

核心结论

优先选择直接更新subscription对应的Apollo缓存,不需要自行维护独立的本地状态。自己维护本地状态很容易出现和服务端、缓存数据不同步的问题,而Apollo的update回调就是专门为了解决mutation后即时更新UI的场景设计的,成本更低、一致性更好。

具体实现方案

你只需要在mutation的update回调中,读取缓存中订阅的帖子列表数据,修改对应帖子的点赞数后写回缓存即可,UI会即时刷新,不需要等待subscription的推送更新。

代码示例

function LikeButton({ postId, ownLiked }) {
  const [insertLike, { loading: likeLoading }] = useMutation(INSERT_LIKE);
  const [deleteLike, { loading: unLikeLoading }] = useMutation(DELETE_LIKE);

  function likePost() {
    insertLike({
      variables: {
        object: {
          user_id: owner,
          post_id: postId,
        },
      },
      update: (cache) => {
        // 1. 读取缓存中的订阅数据,query必须和你的subscription定义完全一致
        const cacheData = cache.readQuery({
          query: GET_POSTS_WITH_OUT_USER
        });
        
        // 2. 找到对应帖子,更新点赞数
        const updatedPosts = cacheData.posts.map(post => {
          if (post.id === postId) {
            return {
              ...post,
              likedCount: {
                ...post.likedCount,
                aggregate: {
                  ...post.likedCount.aggregate,
                  count: post.likedCount.aggregate.count + 1
                }
              },
              // 如果你在subscription中加了当前用户是否点赞的字段,这里顺便更新
              // isLiked: true
            };
          }
          return post;
        });

        // 3. 把修改后的数据写回缓存
        cache.writeQuery({
          query: GET_POSTS_WITH_OUT_USER,
          data: { posts: updatedPosts }
        });
      }
    })
  }

  // 取消点赞的逻辑同理,update中把count减1即可
  function unlikePost() {
    deleteLike({
      variables: { post_id: postId, user_id: owner },
      update: (cache) => {
        const cacheData = cache.readQuery({ query: GET_POSTS_WITH_OUT_USER });
        const updatedPosts = cacheData.posts.map(post => {
          if (post.id === postId) {
            return {
              ...post,
              likedCount: {
                ...post.likedCount,
                aggregate: {
                  ...post.likedCount.aggregate,
                  count: post.likedCount.aggregate.count - 1
                }
              },
              // isLiked: false
            };
          }
          return post;
        });
        cache.writeQuery({ query: GET_POSTS_WITH_OUT_USER, data: { posts: updatedPosts } });
      }
    })
  }

  return (
    <button
      onClick={ownLiked ? unlikePost : likePost}
      disabled={likeLoading || unLikeLoading}
      className={likeLoading || unLikeLoading ? 'cursor-not-allowed' : ''}
    >
      Like
    </button>
  )
}

注意事项

  • 读取和写入缓存时使用的GET_POSTS_WITH_OUT_USER必须和你上层subscription使用的查询完全一致,包括字段、参数、别名,否则会出现读不到缓存或者更新不生效的问题。
  • 如果需要展示当前用户是否已点赞,需要先在subscription的posts查询中添加对应字段,比如用exists语法判断当前用户是否在点赞列表中,更新缓存时同步修改这个字段即可。
  • 后续subscription推送最新数据时会自动覆盖你修改的缓存,不需要担心数据和服务端不一致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:45:02