react-query示例中queryClient.setQueryData执行耗时过长是什么原因?
问题原因与修复方案
核心问题定位
- queryKey未包含依赖参数:当前
useQuery使用固定字符串'Style'作为查询键,没有将入参styleId、pageIndex加入queryKey,导致所有调用useStyle的实例共享同一份查询缓存,任意一个实例请求成功都会触发所有实例的onSuccess回调,大量重复执行setQueryData操作,直接导致更新阻塞。 - initialData配置触发多余回调:配置了
initialData: {},useQuery初始化时会直接使用初始值触发onSuccess,哪怕真实接口请求还未返回,相当于额外多执行一次缓存更新,多实例共存时会瞬间触发几十上百次重复更新。 - 缓存更新逻辑未做结构优化:遍历
pages时无论索引是否匹配,都返回全新的对象,导致所有page的引用全部变更,所有订阅'Styles'缓存的组件会全量重渲染,加剧性能消耗。 - 字段拼写错误引发额外异常:更新缓存时将
pageParams错误拼写为pagesParams,导致更新后分页参数丢失,可能触发额外的分页请求,进一步加剧循环更新。
修复后代码
export const useStyle = (styleId, pageIndex) => { const queryClient = useQueryClient(); const { refetch } = useQuery(['Style', styleId, pageIndex], () => fetchStyle(styleId), { staleTime: Infinity, refetchOnWindowFocus: false, // 移除initialData配置,避免触发多余的onSuccess onSuccess: (res) => { queryClient.setQueryData('Styles', (oldData) => ({ ...oldData, // 先展开原有数据,避免字段丢失 pages: oldData.pages.map((page, index) => { // 非匹配页直接返回原引用,保留结构共享 if (index !== pageIndex) return page return { ...page, Styles: { ...page.Styles, ...res.Styles, }, Groups: { ...page.Groups, ...res.Groups, }, Ranges: { ...page.Ranges, ...res.Ranges, }, } }), })); }, }); return { refetchStyle: refetch }; };
验证方式
可以在onSuccess回调中添加日志打印,确认回调触发次数是否和预期一致,如果修复前触发次数远大于实际请求次数,即可确认是重复执行导致的性能问题。
内容的提问来源于stack exchange,提问作者Kas
相关产品推荐
相关产品推荐

