You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-query如何判断重新请求(refetch)已完成?

问题场景

使用React Query的useQuery获取数据并设置表单初始值,需求是仅在首次挂载获取数据后,以及每次refetch完成后更新表单的初始值。当前遇到的问题是isRefetching仅能标识请求正在进行,无法判断refetch是否完成,不知道何时触发表单初始值的更新。

原始实现代码:
父组件:

const { data: caseData, refetch, isRefetching } = useQuery({
  queryKey: `caseData-${caseId}`,
  queryFn: () => fetchCaseById(caseId),
  staleTime: Infinity,
});

if (!caseData) return "Loading"

<CaseForm initialValues={createInitialValues(caseData)} refetch={refetch}/>

CaseForm组件内的刷新按钮:

<Button
    type="button"
    loading={isRefetching}
    variant="secondary"
    onClick={() => refetch()}
    className="w-max"
    size="small"
>
    Reload
</Button>

尝试过将表单值提升到Context,但仅解决了首次加载的问题,无法感知refetch完成。


解决方案

方法1:利用React Query的data变化自动触发更新(无需Context)

React Query的data会在每次请求(包括refetch)成功完成后更新,我们可以直接在父组件中监听caseData的变化,将处理后的初始值传递给表单,同时在表单内部通过useEffect监听initialValues的变化来重置表单。

父组件调整

const { data: caseData, refetch, isRefetching } = useQuery({
  queryKey: `caseData-${caseId}`,
  queryFn: () => fetchCaseById(caseId),
  staleTime: Infinity,
});

if (!caseData) return "Loading"

const formInitialValues = createInitialValues(caseData);

<CaseForm 
  initialValues={formInitialValues} 
  refetch={refetch}
  isRefetching={isRefetching}
/>

CaseForm组件调整

使用react-hook-form的reset方法,在initialValues变化时重置表单:

import { useForm } from "react-hook-form";

const CaseForm = ({ initialValues, refetch, isRefetching }) => {
  const {
    handleSubmit,
    control,
    reset,
    formState: { errors },
  } = useForm({
    defaultValues: initialValues,
  });

  // 监听initialValues变化,每次更新时重置表单
  useEffect(() => {
    reset(initialValues);
  }, [initialValues, reset]);

  return (
    <>
      {/* 表单内容 */}
      <Button
          type="button"
          loading={isRefetching}
          variant="secondary"
          onClick={() => refetch()}
          className="w-max"
          size="small"
      >
          Reload
      </Button>
    </>
  );
};

这种方式下,每次caseData更新(包括首次加载和refetch完成),父组件都会重新计算formInitialValues,传递给子组件后,子组件通过useEffect触发reset,自动更新表单的初始值。

方法2:结合Context的实现方案

如果必须使用Context管理表单值,可以在父组件中监听caseData的变化,直接更新Context中的值,而不是依赖子组件的判断:

父组件调整

const { caseFormValues, setCaseFormValues } = useCaseProvider();
const { data: caseData, refetch, isRefetching } = useQuery({
  queryKey: `caseData-${caseId}`,
  queryFn: () => fetchCaseById(caseId),
  staleTime: Infinity,
});

if (!caseData) return "Loading"

// 首次加载或每次caseData更新时,更新Context中的表单值
useEffect(() => {
  const formValues = createInitialValues(caseData);
  setCaseFormValues(formValues);
}, [caseData, setCaseFormValues]);

<Suspense fallback="Loading">
    <CaseForm refetch={refetch} isRefetching={isRefetching}/>
</Suspense>

CaseForm组件调整

const { caseFormValues } = useCaseProvider();
const {
  handleSubmit,
  control,
  reset,
  formState: { errors },
} = useForm({
  defaultValues: caseFormValues,
});

// 确保Context值更新时重置表单
useEffect(() => {
  if (caseFormValues) {
    reset(caseFormValues);
  }
}, [caseFormValues, reset]);

// 按钮部分不变

这里的核心是直接监听caseData的变化,因为React Query的data只有在请求成功完成后才会更新,不管是首次加载还是refetch,只要请求成功,caseData就会更新,此时我们就可以触发Context值的更新,进而让表单重置。


关键原理

React Query的data状态是请求成功完成后才会更新的,无论是首次查询还是refetch触发的重新查询,只要请求成功,data就会变成最新值。所以不需要依赖isRefetching来判断完成状态,直接监听data的变化即可准确捕获“数据更新完成”的时机。

内容的提问来源于stack exchange,提问作者Leff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:27:45