reactjs 使用React查询进行变更时未调用ReactsetState

x6492ojm  于 2023-03-12  发布在  React
关注(0)|答案(2)|浏览(75)

bounty将在5天后过期。回答此问题可获得+150的声誉奖励。Leff正在寻找来自声誉良好的来源的答案

我有一个父组件,在其中使用React Query执行API获取:

export default () => {
    const { caseId } = useCaseProvider();
    const { api } = useMockApi();
    const { data: caseData, refetch, isRefetching } = api.getCasaData(caseId);
    const mutation = api.postCaseData(caseId);

    return (
        <Suspense fallback={<Loader size="3xlarge" title="loading..." />}>
            <CaseForm
                caseData={caseData}
                refetch={refetch}
                isRefetching={isRefetching}
                mutation={mutation}
            />
        </Suspense>
    );
};

在CaseForm组件中,由于保存和提交都有按钮,所以我需要根据单击的是哪一个来设置它们的加载状态。为此,我考虑使用useState钩子设置标志:

const CaseForm = ({ caseData, refetch, isRefetching, mutation }) => {
    const { caseFormValues, setCaseFormValues, setActiveStep } = useCaseProvider();
    const initialValues = caseFormValues ?? createInitialValues(caseData);
    const [isSaving, setIsSaving] = useState(false);
    const [isSubmitting, setIsSubmitting] = useState(false);

const onSave = async () => {
    setIsSaving(true);
    await save();
    setIsSaving(false);
};

const save = async () => {
    await mutation.mutate({ ...caseData, ...getValues() });
    setCaseFormValues(getValues());
};

const onSubmit = async () => {
    setIsSubmitting(true);
    await save();
    setIsSubmitting(false);
    setActiveStep(STEPS[Stepper.INCOME]);
};

但是,当我点击这些按钮中的任何一个时,isSubmitting和isSaving总是保持false。我在这里做错了什么,我该如何解决这个问题?

owfi6suc

owfi6suc1#

主要的问题是你的save()函数是async,但是你没有await它,结果是在onSave()期间的序列会马上把isSaving的值设置回false。
由于在下一次渲染中没有变化(isSaving已从false-〉true-〉false发生变化),因此在isSaving值上没有观察到变化。
修复方法是save()save()函数,或重置await之后的变量。
可能的修复

const onSave = async () => {
        setIsSaving(true);
        await save();
        setIsSaving(false);
    };

或者

const onSave = () => {
        setIsSaving(true);
        save();
    };

    const save = async () => {
        await mutation.mutate({ ...caseData, ...getValues() });
        setCaseFormValues(getValues());
        setIsSaving(false);
    };

甚至

const onSave = () => {
        setIsSaving(true);
        save().then(() => setIsSaving(false));
    };

同样的逻辑也适用于onSubmit()

llycmphe

llycmphe2#

您正在使用mutation.mutate沿着await,但这不是一个异步函数。您应该使用可以等待的mutation.mutateAsync,这是两个不同的函数,只有mutateAsync返回Promise。
当像这样使用时,setIsSaving(true)setIsSaving(false)会被快速连续调用,或者作为一个微任务,或者作为下一个tick(不检查就不确定),你看不到它们之间的渲染结果。
旁注:
突变本身有mutation.isLoading,所以最终的问题是为什么要自己复制它。

相关问题