使用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
相关产品推荐
相关产品推荐

