React Query调用mutation前先执行refetch原因及禁用方法咨询
问题原因
你遇到的「调用mutation前先触发查询」的现象,和你配置的useQuery参数、React Query的默认行为有直接关系,常见触发原因如下:
- 定时刷新时机冲突:你给
useQuery配置了refetchInterval: 30000,每30秒自动刷新一次数据,如果触发mutation的时间刚好和定时刷新的触发时机重合,就会出现先执行查询、再执行mutation的观感。 - 查询数据陈旧触发自动刷新:React Query默认的
staleTime为0,也就是说查询拿到返回结果后会立刻被标记为陈旧状态。如果调用mutation时触发了当前组件的重新渲染,符合自动刷新条件时就会先发起查询请求。 - 默认自动刷新规则触发:React Query默认开启了
refetchOnWindowFocus(窗口聚焦时刷新)、refetchOnMount(组件挂载时刷新)、refetchOnReconnect(网络重连时刷新)三个规则,如果你调用mutation刚好符合上述场景,也会先触发查询。
注意你提供的
useMutation代码存在语法问题:第二个参数是配置对象,你需要把onSettled放在{}内包裹,否则代码会直接报错。
禁用前置refetch的方案
你可以根据自己的业务需求选择对应的配置修改:
- 调整定时刷新逻辑
如果是定时刷新和mutation触发时机冲突导致的,可以先临时移除refetchInterval参数验证问题是否消失。如果确认是该原因,可以将refetchInterval配置为函数,在mutation执行期间暂停定时刷新:
const [isMutating, setIsMutating] = useState(false) const { isLoading, isError, data, error, refetch } = useQuery<test>( "test", test, { refetchInterval: () => isMutating ? false : 30000, refetchIntervalInBackground: true } ); // 调用mutation前修改状态,结束后重置 const mutation = useMutation( async (values: VoteProps) => { setIsMutating(true) await fetch("/api/test/test", { method: "POST", body: JSON.stringify(values), headers: { "Content-Type": "application/json", }, }); }, { onSettled: (data: any, error: any, variables: any, context: any) => { setIsMutating(false) refetch(); }, } )
- 关闭不需要的自动刷新规则
给useQuery添加如下配置,关闭默认的自动刷新逻辑:
const { isLoading, isError, data, error, refetch } = useQuery<test>( "test", test, { refetchInterval: 30000, refetchIntervalInBackground: true, refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, staleTime: 5 * 60 * 1000 // 按需设置数据新鲜时间,这段时间内不会自动刷新 } );
- 调用mutation前取消待执行的查询
如果仍偶现冲突,可以在触发mutation前主动取消对应key的查询,避免前置请求发起:
const queryClient = useQueryClient() // 调用mutate前先执行取消逻辑 const handleMutate = (values: VoteProps) => { queryClient.cancelQueries('test') mutation.mutate(values) }
- 优化更新逻辑(可选)
你当前在onSettled中调用refetch拉取最新数据的逻辑可以替换为主动更新缓存,不需要额外发起查询请求,体验更好:
onSuccess: (res) => { // 直接用mutation返回的最新数据更新缓存 queryClient.setQueryData('test', res) }
内容的提问来源于stack exchange,提问作者Maxime Ghéraille
相关产品推荐
相关产品推荐

