如何自定义类似useFormik/useMutation的useAxiosPost Hook?
如何配置自定义useAxiosPost Hook以支持回调函数
1. 定义完整的TypeScript类型
先明确Hook的选项、响应数据和返回值的类型,确保类型安全:
// 通用API响应数据类型,支持自定义返回结构 type ApiResponse<T = unknown> = T; // Hook的配置选项,包含成功/失败回调 interface UseAxiosPostOptions<T = unknown> { onSuccess?: (data: ApiResponse<T>) => void; onError?: (error: Error) => void; } // Hook的返回值,包含请求函数、加载状态和错误信息 interface UseAxiosPostReturn<T = unknown> { post: (url: string, data: unknown) => Promise<void>; loading: boolean; error: Error | null; }
2. 实现Hook核心逻辑
使用useState管理加载状态与错误信息,封装axios POST请求,在请求完成后触发对应回调:
// useAxiosPost.ts import { useState } from 'react'; import axios from 'axios'; type ApiResponse<T = unknown> = T; interface UseAxiosPostOptions<T = unknown> { onSuccess?: (data: ApiResponse<T>) => void; onError?: (error: Error) => void; } interface UseAxiosPostReturn<T = unknown> { post: (url: string, data: unknown) => Promise<void>; loading: boolean; error: Error | null; } function useAxiosPost<T = unknown>({ onSuccess, onError }: UseAxiosPostOptions<T>): UseAxiosPostReturn<T> { const [loading, setLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const post = async (url: string, data: unknown) => { setLoading(true); setError(null); try { const response = await axios.post<ApiResponse<T>>(url, data); // 请求成功时调用传入的onSuccess回调,传递响应数据 onSuccess?.(response.data); } catch (err) { const requestError = err instanceof Error ? err : new Error('请求失败'); setError(requestError); // 请求失败时调用传入的onError回调,传递错误对象 onError?.(requestError); } finally { setLoading(false); } }; return { post, loading, error }; } export default useAxiosPost;
3. 组件中使用Hook
通过泛型指定响应数据类型,传入回调函数处理请求结果,同时可以直接使用Hook返回的状态控制UI:
import useAxiosPost from './useAxiosPost'; // 定义API返回的数据结构 interface UserResponse { id: number; name: string; email: string; } function UserForm() { const { post, loading, error } = useAxiosPost<UserResponse>({ onSuccess(data) { // 处理成功返回的数据,比如更新状态、跳转页面 console.log('用户创建成功:', data); }, onError(error) { // 处理请求错误,比如展示提示 console.error('创建用户失败:', error.message); }, }); const handleCreateUser = async () => { const formData = { name: '李四', email: 'lisi@example.com' }; await post('/api/users', formData); }; if (loading) return <div>提交中...</div>; if (error) return <div className="error">错误:{error.message}</div>; return ( <button onClick={handleCreateUser} disabled={loading}> 创建用户 </button> ); } export default UserForm;
核心设计要点
- 泛型支持:通过
<T>适配不同API的响应结构,组件使用时可获得完整的类型提示。 - 状态封装:Hook内部维护
loading和error状态,无需组件自行管理。 - 回调触发:请求完成后自动调用传入的
onSuccess/onError,与useMutation、useFormik的回调模式保持一致。
内容的提问来源于stack exchange,提问作者Bikrant
相关产品推荐
相关产品推荐

