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

如何从React Query自定义mutation中解构获取data、error、isLoading

问题原因

你当前的实现存在两个核心问题,导致拿不到请求的全量状态:

  1. 所有请求错误都在try/catch块中被吞掉,没有向上层抛出,React Query无法捕获到失败状态
  2. 没有使用React Query内置的useMutation钩子托管请求生命周期,手动封装的异步函数不会自动维护isLoading/data/error这类响应式状态

修正方案

第一步:修改服务层逻辑,不要吞错误

服务层只负责发起请求,不要在内部捕获错误后直接结束,如果需要打印错误日志,捕获后必须重新抛出,保证错误能传递到React Query层:

const getMutationService = () => {
  return {
    editProfile: async (
      displayName: string,
      privateProfile?: boolean,
    ): Promise<AuthEditMeResponse> => {
      try {
        const result = await userApi.mePost({
          payload: {
            display_name: displayName,
            _private: privateProfile,
          },
        });
        return result;
      } catch (error) {
        console.log("User Edit Profile Error", error);
        // 关键:打印日志后必须把错误向上抛出,否则上层感知不到失败
        throw error;
      }
    },
  };
};

第二步:在自定义Hook中直接使用useMutation托管状态

React Query的useMutation本身已经内置维护了请求全周期的所有状态,不需要自己手动封装异步函数,直接把请求方法传入即可:

const useUserProfile = () => {
  const queryClient = useQueryClient();
  const mutationService = getMutationService();

  const editProfileMutation = useMutation({
    // 定义触发mutation时执行的请求方法
    mutationFn: ({
      displayName,
      privateProfile,
    }: {
      displayName: string;
      privateProfile?: boolean;
    }) => mutationService.editProfile(displayName, privateProfile),
    // 可选:请求成功后的回调,一般用来刷新相关缓存
    onSuccess: () => {
      // 比如刷新当前登录用户的信息缓存
      queryClient.invalidateQueries({ queryKey: ["auth"] });
    },
  });

  // 直接把mutation实例返回给组件使用
  return editProfileMutation;
};

export default useUserProfile;

第三步:组件中调用即可拿到全量状态

组件引入自定义Hook后,直接解构需要的状态和触发方法即可:

const ProfileEditPage = () => {
  const {
    mutate: editProfile,
    isLoading,
    data,
    error,
    isError,
    reset
  } = useUserProfile();

  const handleSave = () => {
    editProfile({
      displayName: "测试昵称",
      privateProfile: true
    })
  }

  if (isLoading) return <div>资料保存中...</div>
  if (isError) return <div>保存失败:{(error as Error).message} <button onClick={reset}>重试</button></div>

  return (
    <div>
      {data && <div>保存成功!最新昵称:{data.displayName}</div>}
      <button onClick={handleSave}>保存个人资料</button>
    </div>
  )
}

关键注意点
  • 不要在请求链路的任意层无理由吞掉错误,只要使用了try/catch捕获错误做日志、特殊处理,最后必须加throw error把错误继续向上传递,否则React Query永远无法进入error状态
  • useMutation返回的常用状态除了isLoading/data/error,还有isError/isSuccess/reset/mutateAsync等能力,覆盖绝大多数请求场景,不需要额外手动维护状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:27:17