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

如何在React Query中跨组件订阅mutation状态变化

跨组件订阅React Query Mutation状态的解决方案

问题原因

你当前的代码中,每个组件调用useUpdateResidence时都会创建独立的Mutation实例,不同实例的状态完全隔离,所以其他组件无法感知表单组件触发的Mutation状态变化。

解决方法

方法1:利用React Query的Mutation Key共享实例

给useMutation添加唯一的mutationKey,确保相同caseId下的Mutation复用同一个实例,状态自动同步。

修改useUpdateResidence钩子:

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

    const mutation = useMutation({
        // 新增mutationKey,用caseId区分不同案件的更新操作
        mutationKey: ["update-residence", caseId],
        mutationFn: async (payload: UpdateResidenceRequest): Promise<CaseResponse> => {
            const { data } = await CASE_API.api.updateCase(caseId, payload);
            return data;
        },
        onSuccess: (data) => {
            queryClient.setQueryData(["case", caseId], data);
            setError(undefined);
        },
        onError: (error) => {
            console.log("onError", error);
            setError(error);
        },
    });

    return { mutation, error };
};

之后其他组件只需传入相同的caseId调用useUpdateResidence,就能拿到同一个Mutation实例,实时获取状态变化。

方法2:通过React Context共享Mutation实例

创建Context将Mutation实例注入到组件树中,让需要订阅状态的组件从Context中获取同一个实例。

  1. 创建Context和Provider:
import { createContext, useContext, ReactNode } from 'react';
import { useUpdateResidence } from './path-to-your-hook';

const UpdateResidenceMutationContext = createContext<ReturnType<typeof useUpdateResidence> | null>(null);

export const UpdateResidenceMutationProvider = ({ 
    caseId, 
    children 
}: { 
    caseId: number; 
    children: ReactNode 
}) => {
    const mutationData = useUpdateResidence(caseId);
    return (
        <UpdateResidenceMutationContext.Provider value={mutationData}>
            {children}
        </UpdateResidenceMutationContext.Provider>
    );
};

// 自定义钩子简化Context获取
export const useSharedUpdateResidenceMutation = () => {
    const context = useContext(UpdateResidenceMutationContext);
    if (!context) {
        throw new Error('useSharedUpdateResidenceMutation must be used within UpdateResidenceMutationProvider');
    }
    return context;
};
  1. 在表单组件的父层级包裹Provider:
// 假设父组件中能获取到caseId
const { caseId } = useCase();

return (
    <UpdateResidenceMutationProvider caseId={caseId}>
        <FormComponent />
        <OtherComponentThatNeedsMutationState />
    </UpdateResidenceMutationProvider>
);
  1. 在表单和订阅组件中使用共享钩子:
// 表单组件中
export const useOnSaveCase = () => {
    const { reset } = useFormContext<CaseFormValues>();
    const updateCase = useSharedUpdateResidenceMutation();
    return (values: CaseFormValues) => {
        updateCase.mutation.mutate(createPayload(values), {
            onSuccess: () =>
                reset(values, {
                    keepErrors: true,
                    keepValues: true,
                    keepDefaultValues: true,
                    keepDirtyValues: true,
                }),
        });
    };
};

// 订阅组件中
const caseMutation = useSharedUpdateResidenceMutation();
console.log("is pending", caseMutation.mutation.isPending);
console.log("is success", caseMutation.mutation.isSuccess);

方法3:通过Mutation Cache手动订阅状态

如果只需要监听状态而不需要触发Mutation,可以直接从React Query的Mutation Cache中获取实例并订阅。

import { useQueryClient } from '@tanstack/react-query';
import { useCase } from './path-to-your-hooks';

const MutationStatusWatcher = () => {
    const { caseId } = useCase();
    const queryClient = useQueryClient();

    useEffect(() => {
        // 根据mutationKey查找对应的Mutation实例
        const mutation = queryClient.getMutationCache().find(["update-residence", caseId]);
        if (!mutation) return;

        // 订阅状态变化
        const unsubscribe = mutation.subscribe((state) => {
            console.log("is pending", state.isPending);
            console.log("is success", state.isSuccess);
        });

        // 组件卸载时取消订阅
        return unsubscribe;
    }, [caseId, queryClient]);

    return null;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:58:11