You need to enable JavaScript to run this app. 使用react-query的prefetchQuery预取数据,网络有响应但缓存无对应数据的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

使用react-query的prefetchQuery预取数据,网络有响应但缓存无对应数据的问题排查

代码存在的核心问题
  • 查询函数传参方式完全不符合react-query要求
    当前传给prefetchQuery的第二个参数,是已经执行的异步函数返回的Promise实例:getSubCategoryListByCategoryId(item._id)这行代码在调用prefetchQuery时就已经触发了网络请求,因此浏览器Network面板能看到请求成功返回。但react-query要求这个位置传入的是可以返回Promise的函数引用,而非已经生成的Promise对象。这就导致react-query根本没有接管这个请求的生命周期,拿到响应后也不知道要把对应数据和那个查询key绑定存储,最终只会在缓存里生成空的key占位,存不进实际数据。
  • 副作用执行时机不对
    预取逻辑放在了依赖为空[]的useEffect中,组件首次渲染时categoryList接口的data还未返回,dataList是undefined,循环逻辑根本跑不起来。哪怕把函数传对了,预取操作也不会真正执行。
  • 异常处理存在漏洞
    getSubCategoryListByCategoryId的catch分支只打印错误日志,没有重新抛出异常,接口报错时函数会返回undefined,也会导致缓存无法写入有效数据。
修正后的实现

首先调整prefetchQuery的传参方式,把已经执行的Promise改成返回Promise的函数:

queryClient.prefetchQuery(
  ['subCategoryListByCategoryId', item._id],
  () => getSubCategoryListByCategoryId(item._id)
)

然后调整useEffect的逻辑,增加空值判断、修正依赖,等categoryList数据加载完成后再触发预取:

useEffect(() => {
  // 数据未加载完成时直接跳过,避免报错
  if (!dataList) return;
  
  setValues({ ...values, categories: dataList });

  dataList.forEach((item) => {
    queryClient.prefetchQuery(
      ['subCategoryListByCategoryId', item._id],
      () => getSubCategoryListByCategoryId(item._id)
    );
  });
}, [dataList]);

可以利用react-query的传参机制简化代码:查询函数会自动接收到包含queryKey的上下文对象,不需要手动在箭头函数里传入id参数:

// 调整查询函数,自动接收react-query传入的queryKey参数
async function getSubCategoryListByCategoryId({ queryKey }) {
  const [, categoryId] = queryKey; // 从查询key中解构出分类id
  const { data } = await axios.request({
    baseURL,
    url: `/category/subcategories/${categoryId}`,
    method: 'get',
  });
  return data;
}

// 调用prefetchQuery时直接传入函数引用即可
queryClient.prefetchQuery(
  ['subCategoryListByCategoryId', item._id],
  getSubCategoryListByCategoryId
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 02:54:05