react-query设置staleTime后onSuccess未触发无法初始化表单怎么办?
问题核心原因
你遇到的是TanStack Query(原React Query)的默认设计行为:onSuccess回调仅在网络请求成功返回新数据时触发,当数据命中staleTime内的缓存、未发起实际网络请求时,onSuccess不会执行。
无需使用useEffect的解决方案
方案1:改造自定义query hook,兼容缓存数据触发回调
你可以修改useGetUserDetailsQuery的内部逻辑,只要拿到有效数据(不管来源是缓存还是新请求)就执行传入的回调,业务组件不需要做任何改动:
import { useRef } from 'react'; export const useGetUserDetailsQuery = ( onSuccess?: (stateData: GetUserDetailsQueryResp) => void, ): UseQueryResult<GetUserDetailsQueryResp, ErrorResponse> => { // 用ref存储上一次已经处理过的数据,避免重复执行回调 const lastProcessedDataRef = useRef<GetUserDetailsQueryResp | null>(null); const queryResult = useGraphqlQuery('get-user-details', GET_USER_DETAILS, { staleTime: 600000, // 保留原有逻辑,处理网络请求返回的新数据 onSuccess: (data) => { onSuccess?.(data); lastProcessedDataRef.current = data; }, }); // 渲染时判断:存在未处理的缓存数据就直接执行回调 if (queryResult.data && queryResult.data !== lastProcessedDataRef.current) { onSuccess?.(queryResult.data); lastProcessedDataRef.current = queryResult.data; } return queryResult; };
方案2:使用TanStack Query v5的onData回调
如果你已经升级到TanStack Query v5版本,可以直接把onSuccess替换为新增的onData回调,该回调的设计就是无论数据来源是缓存还是网络请求,只要查询拿到有效数据就会触发:
export const useGetUserDetailsQuery = ( onData?: (stateData: GetUserDetailsQueryResp) => void, ): UseQueryResult<GetUserDetailsQueryResp, ErrorResponse> => { return useGraphqlQuery('get-user-details', GET_USER_DETAILS, { staleTime: 600000, onData: onData, }); };
业务组件直接把setInitalState作为onData参数传入即可,不需要其他改动。
注意事项
不要在业务组件里直接写data && setInitalState(data)这类逻辑,否则会因为组件重复渲染触发多次dispatch,用ref缓存上一次处理的数据可以完全规避这个问题。
内容的提问来源于stack exchange,提问作者Ishan jain
相关产品推荐
相关产品推荐

