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

Sanity查询无法稳定返回更新后数据问题求助

问题:Sanity添加评论后无法稳定获取更新后的评论列表

我的Sanity数据库中有一个film类型,包含一个评论数组。UI里展示影片图片和下方的评论列表,同时编写了添加评论并重新获取影片数据的函数。

在addCommentToFilm函数中,通过patch请求提交评论添加操作,commit返回的Promise结果里包含已更新的评论数组(含刚添加的评论),但调用fetchFilm获取数据时,评论数组有时不包含最新评论,得多次调用才能拿到完整更新后的列表。

const addCommentToFilm = (filmId) => {
      client
        .patch(filmId)
        .setIfMissing({ comments: [] })
        .insert('after', 'comments[-1]', [{
          comment,
          _key: uuidV4(),
          postedBy: {
            _type: 'postedBy',
            _ref: user._id,
          }
        }])
        .commit()
        .then((res) => {
          console.log(res); // 这里能拿到包含新评论的影片数据
          fetchFilms(filmId);
        })
        .catch((error) => {
          console.log('Comment post error: ', error);
        })
  }

  const fetchFilm = (filmId) => {
    client
      .fetch(`*[_type == "film" && _id == "${filmId}"]`)
      .then((res) => console.log(res)) // 有时能拿到新评论,有时拿不到
  }

原因分析

这是Sanity的读写分离+缓存机制导致的:

  • 写入操作(patch/commit)会直接更新主数据库,返回的结果是主节点的最新数据;但读取操作(fetch)默认会从边缘节点的缓存获取数据,缓存同步到主节点的更新需要一定时间,所以刚写完就读可能拿到旧数据。
  • commit返回的是写入操作的即时确认结果,但全局读取节点的缓存还没完成同步,导致后续fetch偶尔拿到旧数据。

稳定获取更新数据的解决方法

方法一:直接用commit返回的结果更新UI(最优解)

既然commit的返回值已经包含了最新的影片数据(包括刚添加的评论),直接用这个结果更新你的状态(比如React的state),完全不需要再调用fetchFilm。既解决缓存问题,还减少了一次API请求。

修改示例:

const addCommentToFilm = (filmId) => {
  client
    .patch(filmId)
    .setIfMissing({ comments: [] })
    .insert('after', 'comments[-1]', [{
      comment,
      _key: uuidV4(),
      postedBy: {
        _type: 'postedBy',
        _ref: user._id,
      }
    }])
    .commit()
    .then((updatedFilm) => {
      console.log('更新后的影片数据:', updatedFilm);
      // 直接用updatedFilm更新你的状态,比如setFilm(updatedFilm)
    })
    .catch((error) => {
      console.log('评论提交错误: ', error);
    })
}

方法二:强制fetch跳过缓存

如果必须调用fetchFilm(比如有其他依赖场景),可以在请求中添加cache: 'no-cache'参数,强制从主节点获取最新数据:

const fetchFilm = (filmId) => {
  client
    .fetch(`*[_type == "film" && _id == "${filmId}"]`, {}, { cache: 'no-cache' })
    .then((res) => console.log(res))
}

方法三:使用实时订阅功能

对于需要实时同步数据的场景,可以用Sanity的listen功能订阅影片数据变化,当数据更新时自动触发UI更新:

// 订阅指定影片的数据变化
const subscribeToFilm = (filmId) => {
  client
    .listen(`*[_type == "film" && _id == "${filmId}"]`)
    .subscribe((update) => {
      if (update.type === 'mutation') {
        // 更新UI状态
        setFilm(update.result);
      }
    });
}

内容的提问来源于stack exchange,提问作者Scott F.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:41:27