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

Next.js+TypeScript中使用SWR Hook更新缓存如何避免重拉取新增帖子?

解决方案

问题根源

你当前遇到的问题来源于评论/点赞操作完成后,调用了无参数的mutate方法:SWR在只传入缓存key的情况下,会默认触发该key对应接口的全量重请求,拉取到其他用户发布的新帖后就会覆盖本地缓存,导致原有帖子排序变化。

代码修改方案

1. 优化评论提交逻辑

你已经做了本地缓存的乐观更新,只需要移除后续触发全量重拉的mutate调用即可;如果需要对齐服务端返回的最新数据,可让createComment接口返回更新后的单条帖子数据,再用该数据更新缓存即可,全程不需要触发全量接口请求。
修改后的handleSubmit代码如下:

// Create comment
const handleSubmit = async (e: FormEvent<HTMLFormElement>): Promise<void> => {
  e.preventDefault();
  // 先缓存原有数据,用于出错回滚
  const originalPubs = mutate(`${process.env.URL}/api/publication`, (allPubs: Ipublication[]) => {
    // 这里优化原查找逻辑,用_id匹配代替引用匹配,避免找不到对应帖子
    const currentPub = allPubs.find(f => f._id === publication._id);
    const updatePub = allPubs.map(pub =>
      pub._id === currentPub._id
        ? {
            ...currentPub,
            comments: [
              {
                body: commentBody,
                createdAt: new Date().toISOString(),
                identifier: userAuth.user.id,
                name: userAuth.user.name
              },
              ...currentPub.comments
            ]
          }
        : pub
    );
    return updatePub;
  }, false); // 第三个参数传false,关闭重验证

  try {
    // 可让createComment接口返回更新后的当前帖子完整数据
    const updatedPub = await createComment(
      { identifier: userAuth.user.id, body: commentBody },
      publication._id
    );
    // 可选:用服务端返回的最新数据更新缓存,依旧关闭重验证
    mutate(`${process.env.URL}/api/publication`, (allPubs: Ipublication[]) => {
      return allPubs.map(pub => pub._id === updatedPub._id ? updatedPub : pub);
    }, false);
  } catch (err) {
    // 出错时回滚到原有缓存数据,不要触发全量拉取
    mutate(`${process.env.URL}/api/publication`, originalPubs, false);
  }
};

2. 点赞逻辑参考修改

和评论逻辑一致,先做乐观更新,接口请求完成后用返回数据对齐缓存,全程不触发全量重拉即可。

3. 用户自主发帖新增逻辑

当用户自己发布新帖时,手动将新帖子插入缓存列表头部即可,实现示例:

const handleCreatePub = async (newPubData) => {
  try {
    // 提交新帖到服务端,接口返回新帖完整数据
    const createdPub = await createNewPub(newPubData);
    // 将新帖插入缓存列表头部,关闭重验证
    mutate(`${process.env.URL}/api/publication`, (allPubs: Ipublication[]) => {
      return [createdPub, ...allPubs];
    }, false);
  } catch (err) {
    // 自定义错误处理逻辑
  }
}

额外优化建议

如果需要完全避免页面后续任何场景的全量帖子拉取,可在useSWR的配置项中新增revalidateOnMount: false,关闭组件挂载时的自动重验证:

const { data: Publications }: thePublication = useSWR(
  `${process.env.URL}/api/publication`,
  {
    initialData: allPubs,
    revalidateOnFocus: false,
    revalidateOnMount: false // 新增该配置
  }
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 14:24:02