React-Query中useCallback依赖数据未更新的原因排查
React Query refetch后useCallback拿旧数据但useEffect拿新数据的原因
核心原因
问题出在React Query的状态更新时机和React渲染周期的同步逻辑不匹配上,具体拆解如下:
- refetch的异步更新逻辑
await templatesListQuery.refetch()只是等待网络请求完成,但React Query更新内部data状态的操作会触发组件重新渲染——这个状态更新和组件重渲染是异步的,不会在handleTemplateDataSubmit函数执行的同步流程里完成。
当你在await refetch()之后立刻调用updateCurrentActiveTemplate时,当前代码仍处于旧渲染周期,此时templatesListQuery.data还是旧值,而useCallback缓存的函数实例也是基于旧data创建的,自然输出旧数据。
useEffect的触发时机
当React Query完成data更新后,组件会触发重新渲染。此时useEffect的依赖项templatesListQuery.data发生变化,useEffect会在新的渲染周期执行,所以能拿到最新的data。useCallback的缓存机制
useCallback会根据依赖项缓存函数实例,只有当templatesListQuery.data更新后,才会生成新的函数实例。但在handleTemplateDataSubmit执行的当下,新的函数实例还未生成,你调用的始终是旧渲染周期里缓存的版本。
解决办法
如果需要在refetch完成后基于最新数据执行逻辑,最直接的方式是利用React Query的onSuccess回调:
const handleTemplateDataSubmit = () => { templatesListQuery.refetch({ onSuccess: (newData) => { // 这里能直接拿到最新的请求返回数据 console.log(newData); // 执行你的业务逻辑,比如替换原updateCurrentActiveTemplate的逻辑 } }); }
内容的提问来源于stack exchange,提问作者ChenLee
相关产品推荐
相关产品推荐

