React-query – 如何检查重新获取已完成

huangapple go评论61阅读模式
英文:

React-query - how to check when refetching has been finished

问题

我有一个组件,在该组件中,我使用react-query来获取数据并设置初始表单值:

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组件中,我有一个按钮,当单击时触发refetch函数:

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

我想在数据首次获取后以及后续的refetch后,仅创建初始值一次。我考虑将表单值提升到上下文提供程序中,以便在那里检查状态。类似以下方式:

const { data: caseData, refetch, isRefetching } = api.getCaseData(caseId);

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

然后在CaseForm中:

const { caseFormValues, setCaseFormValues } = useCaseProvider();

useEffect(() => {
  if (!caseFormValues) setCaseFormValues(initialValues);
}, []);

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

这可以帮助我在首次获取数据时设置初始值,但如何在数据完成重新获取后检查数据是否已重新获取,以便更新表单值呢?我无法使用isRefetching,因为它只在数据开始重新获取时显示。不确定如何检查这一点。

英文:

I have a component where I am fetching data with react-query and setting initial form values:

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

if (!caseData) return &quot;Loading&quot;

&lt;CaseForm initialValues={createInitialValues(caseData)} refetch={refetch}/&gt;

Inside a CaseForm component I have a button that onClick triggers refetch function:

&lt;Button
    type=&quot;button&quot;
    loading={isRefetching}
    variant=&quot;secondary&quot;
    onClick={() =&gt; refetch()}
    className=&quot;w-max&quot;
    size=&quot;small&quot;
&gt;
    Reload
&lt;/Button&gt;

I would like to only create initial values once after data is fetched first time on mount and later on refetch. I thought of lifting form values into context provider so that i can check state there. Something like this:

const { data: caseData, refetch, isRefetching } = api.getCaseData(caseId);

&lt;Suspense fallback=&quot;Loading&quot;&gt;
    &lt;CaseForm initialValues={caseData} refetch={refetch}/&gt;
&lt;/Suspense&gt;

And then in CaseForm:

const { caseFormValues, setCaseFormValues } = useCaseProvider();

useEffect(() =&gt; {
  if (!caseFormValues) setCaseFormValues(initialValues);
}, []);

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

That can help me with initial values when data is being fetched for the first time, but how can I check if data has been refetched, once it is finished being refetched so that I can updated form values?
I can't use isRefetching since that only shows when data has started refetching. Not sure how can I check this?

答案1

得分: 1

Sure, here is the translation of the code-related part:

// Callback of the refetching
const handleRefetch = () => {
  refetch().then(res => {
    setCaseFormValues(res?.data)  // updated data here

    // do whatever you want here...
  })
}

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

If you need further translation or have other code-related questions, please feel free to ask.

英文:

UPDATED ANSWER:

> I want to know when data has arrived after refetch, and only in case of a refetch.

Well, the refetch() function returns a promise, so just do what you want after it completed. So inside that promise, you don't need to check condition whether this is a initial loading or the refetching.

// Callback of the refetching
const handleRefetch = () =&gt; {
  refetch().then(res =&gt; {
    setCaseFormValues(res?.data)  // updated data here

    // do whatever you want here...
  })
}

&lt;Button
  type=&quot;button&quot;
  loading={isRefetching}
  variant=&quot;secondary&quot;
  onClick={handleRefetch}
  className=&quot;w-max&quot;
  size=&quot;small&quot;
&gt;
  Reload
&lt;/Button&gt;

INITIAL ANSWER:

You don't need to handle this yourself. react-query provides an option enabled.

enabled is true by default, which means the query is triggered automatically by react-query. You can set enabled: false to disable this automation, so that it will only run 1st time on mounting, then it only runs to get new data on the time you call refetch().


One more thing, react-query has 3 different variables to tracking the fetching states, which are:

  • isLoading:

    Is true if the query is in a "hard" loading state. This means there is no cached data and the query is currently fetching (isLoading = true only at the 1st query when component is mounted).

  • isFetching:

    Is true whenever a request is in-flight, which includes initial loading as well as background refetches.

    Will be true if the query is currently fetching, including background fetching.

  • isRefetching:

    Is true whenever a background refetch is in-flight, which does not include initial loading.

    Is the same as isFetching &amp;&amp; !isLoading.

You can find more from the docs.

Hope this can help!

huangapple
  • 本文由 发表于 2023年2月27日 07:25:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575632.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定