如何从React Query自定义mutation中解构获取data、error、isLoading
问题原因
你当前的实现存在两个核心问题,导致拿不到请求的全量状态:
- 所有请求错误都在
try/catch块中被吞掉,没有向上层抛出,React Query无法捕获到失败状态 - 没有使用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
相关产品推荐
相关产品推荐

