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

React Query自定义hook错误状态未传递至调用组件问题

React Query useMutation 自定义hook中错误状态无法传递到组件的问题

我在项目中使用React Query,在自定义hook里使用useMutation时遇到问题:所有查询类自定义hook都放在useApiData文件中,其中useUpdateCase的代码如下:

export const useUpdateCase = (caseId: number) => {
    const queryClient = useQueryClient();
    const [error, setError] = useState(undefined);

    const mutation = useMutation({
        mutationFn: (payload: UpdateCaseRequest): Promise<AxiosResponse<CaseDto>> =>
            CASE_API.api.updateCase(caseId, payload),
        onSuccess: (data) => {
            queryClient.setQueryData(["case", caseId], data);
            console.log("onSuccess");
            setError(undefined);
        },
        onError: (error) => {
            console.log("onError", error);
            setError(error);
        },
    });

    console.log("error", error);
    console.log("mutation", mutation);
    return { mutation, error };
};

我通过Mock Service Worker返回503状态码模拟错误场景,MSW代码如下:

rest.put(`${environment.url.case}/api/case/:caseId`, async (req, res, ctx) => {
            const body = await req.json();
            const existingCase = JSON.parse(localStorage.getItem(`case-${req.params.caseId}`));
            const updatedCase = { ...existingCase, ...body };

            const sucessHeaders = [
                ctx.set("Content-Type", "application/json"),
                ctx.status(200),
                ctx.body(JSON.stringify(updatedCase)),
            ];
            const errorHeaders = [
                ctx.status(503),
                ctx.json({
                    errorMessage: "Service Unavailable",
                }),
            ];

            const index = 1; //Math.random() < 0.9 ? 0 : 1;
            const response = [sucessHeaders, errorHeaders];

            // if (index === 0) {
            //     localStorage.setItem(`case-${req.params.caseId}`, JSON.stringify(updatedCase));
            // }

            return res(...response[index]);
        }),

但在调用该自定义hook的组件中:

const updateCase = useUpdateCase(caseId);

console.log("updateCase", updateCase);

发生错误时,updateCase并未更新,组件中无对应日志输出,但hook内已打印错误。控制台日志如下:

updateCase {mutation: {…}, error: undefined}
useApiData.tsx:48 error AxiosError {message: 'Request failed with status code 503', name: 'AxiosError', code: 'ERR_BAD_RESPONSE', config: {…}, request: XMLHttpRequest, …}
useApiData.tsx:49 mutation {context: undefined, data: undefined, error: AxiosError, failureCount: 1, failureReason: AxiosError, …}

请问哪里操作有误,为何更新后的错误状态无法传递至调用组件?


问题原因与解决方案

核心问题是你冗余维护了一个独立的useState错误状态,而React Query的useMutation本身已经内置了响应式的error状态,额外的状态不仅没必要,还会导致状态不同步、组件无法感知更新的问题。

修正步骤:

  1. 移除自定义hook中自己声明的error状态及相关setError调用
  2. 直接返回useMutation生成的mutation对象,组件从mutation中直接获取错误状态

修正后的useUpdateCase代码:

export const useUpdateCase = (caseId: number) => {
    const queryClient = useQueryClient();

    const mutation = useMutation({
        mutationFn: (payload: UpdateCaseRequest): Promise<AxiosResponse<CaseDto>> =>
            CASE_API.api.updateCase(caseId, payload),
        onSuccess: (data) => {
            queryClient.setQueryData(["case", caseId], data);
            console.log("onSuccess");
        },
        // 无需额外处理错误,useMutation会自动更新mutation.error
    });

    console.log("mutation", mutation);
    return mutation;
};

组件中调用方式:

// 直接获取mutation对象,或按需解构
const { mutate, error, isError } = useUpdateCase(caseId);

// 可以在组件中通过useEffect监听错误变化,或者直接在JSX中使用
console.log("当前错误状态", error);

为什么原写法无效?

  • 你自己维护的error状态在更新后,虽然hook会重新执行,但组件若未显式依赖该状态(比如未在JSX中使用或通过useEffect监听),可能不会触发重新渲染,导致组件打印的仍是旧值
  • React Query的mutation对象本身是响应式的,当mutation状态(如error)变化时,useMutation会自动触发组件重新渲染,不需要额外维护状态
  • 原代码中返回的error和mutation.error可能存在闭包导致的不同步问题,属于冗余且易出错的写法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:42:42