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

使用React Query时,点击按钮后useState状态未更新问题排查

问题根源

你代码里的核心问题是错误使用了React Query的mutate方法。mutate是基于回调的异步操作,它不会返回Promise,所以await mutation.mutate(...)根本不会等待API请求完成——save函数会立刻执行完毕,导致setIsSaving(false)或setIsSubmitting(false)几乎和设为true的操作同步执行,状态还没来得及更新就被重置,自然看不到加载状态变化。

修复方案

有两种可行的修复方式,推荐第二种(利用React Query内置状态):

方案一:改用mutateAsync实现等待

React Query提供了mutateAsync方法,它会返回Promise,支持await等待请求完成。修改你的save函数:

const save = async () => {
    // 把mutate替换为mutateAsync
    await mutation.mutateAsync({ ...caseData, ...getValues() });
    setCaseFormValues(getValues());
};

修改后await save()会真正等待API请求结束,状态会保持为true直到请求完成。

方案二:使用React Query内置的mutation状态(推荐)

React Query的mutation对象本身自带isLoading(新版本可能叫isPending)状态,用来标识当前mutation是否在执行中。你完全不需要自己维护isSaving和isSubmitting,既简化代码又避免状态不同步:

  1. 父组件传递mutation时,把内置状态也传进去:
// 父组件中
const { mutate, isLoading } = api.postCaseData(caseId);
// 传递给CaseForm
<CaseForm
    caseData={caseData}
    refetch={refetch}
    isRefetching={isRefetching}
    mutate={mutate}
    isMutating={isLoading}
/>
  1. CaseForm组件中移除自定义状态,结合操作类型判断加载状态:
const CaseForm = ({ caseData, refetch, isRefetching, mutate, isMutating }) => {
    const { caseFormValues, setCaseFormValues, setActiveStep } = useCaseProvider();
    const initialValues = caseFormValues ?? createInitialValues(caseData);
    // 移除自定义的useState
    // const [isSaving, setIsSaving] = useState(false);
    // const [isSubmitting, setIsSubmitting] = useState(false);

    // 新增一个状态标识当前操作类型
    const [currentAction, setCurrentAction] = useState(null);

    const save = async (onSuccess) => {
        await mutate.mutateAsync({ ...caseData, ...getValues() }, {
            onSuccess: () => {
                setCaseFormValues(getValues());
                onSuccess?.();
                setCurrentAction(null);
            },
            onError: () => {
                setCurrentAction(null);
            }
        });
    };

    const onSave = () => {
        setCurrentAction('save');
        save();
    };

    const onSubmit = () => {
        setCurrentAction('submit');
        save(() => {
            setActiveStep(STEPS[Stepper.INCOME]);
        });
    };

    // 渲染按钮时这样判断加载状态
    // <Button loading={isMutating && currentAction === 'save'}>保存</Button>
    // <Button loading={isMutating && currentAction === 'submit'}>提交</Button>
};

这种方式完全遵循React Query的设计思路,不用手动管理异步状态,减少出错概率。

额外提醒
  • 如果你使用的是React Query v4+,isLoading已被重命名为isPending,请对应调整。
  • 如果不需要区分两种操作的加载状态,甚至连currentAction都可以省略,直接用isMutating控制所有按钮的加载状态。

内容的提问来源于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 09:02:05