如何在ReactJS应用中标准化API请求的错误处理
解决React中API错误处理重复冗余的方案
不用找复杂框架,自己封装一套复用逻辑就够了,既灵活又能适配你的API错误格式,还能避免到处改代码的麻烦。下面分两步来实现:
第一步:给Axios加全局错误拦截器
先统一处理所有API请求的错误,把各种格式的错误转换成标准化结构,这样组件里不用每次都解析error.response.data。
// src/utils/axios.js import axios from 'axios'; const api = axios.create({ baseURL: '你的API基础地址', }); // 响应错误拦截器 api.interceptors.response.use( response => response, error => { let standardizedError = { type: 'UNKNOWN', // 默认类型 generalMessages: [], fieldErrors: [], }; // 1. API返回的错误(有response.data.error) if (error.response?.data?.error) { const errorPayload = error.response.data.error; standardizedError.type = 'API_ERROR'; // 处理通用错误消息 if (errorPayload.messages) { standardizedError.generalMessages = Array.isArray(errorPayload.messages) ? errorPayload.messages : [errorPayload.messages]; } // 处理字段验证错误 if (errorPayload.validationErrors) { standardizedError.fieldErrors = errorPayload.validationErrors.map(err => ({ field: err.fieldName, message: err.message, })); } } // 2. Axios生成的错误(超时、无响应、404/500等) else { standardizedError.type = 'NETWORK_ERROR'; standardizedError.generalMessages = [error.message || '请求失败,请稍后重试']; } // 把标准化后的错误抛出去 return Promise.reject(standardizedError); } ); export default api;
第二步:封装自定义Hook处理请求状态和错误
把请求状态(加载中、成功、错误)、错误处理逻辑封装成Hook,不管是表单提交还是普通PATCH请求都能复用。
// src/hooks/useApiRequest.js import { useState, useCallback } from 'react'; import { fieldNameTransformer } from '你的字段转换工具路径'; export const useApiRequest = (setError = null) => { const [requestStatus, setRequestStatus] = useState('input'); const [generalRequestError, setGeneralRequestError] = useState(null); const handleRequest = useCallback(async (apiCall, onSuccess) => { if (requestStatus === 'requesting') return; setRequestStatus('requesting'); setGeneralRequestError(null); try { const response = await apiCall(); setRequestStatus('success'); onSuccess?.(response); } catch (standardizedError) { // 区分错误类型处理UI状态 if (standardizedError.type === 'API_ERROR' && standardizedError.fieldErrors.length > 0) { setRequestStatus('input'); } else { setRequestStatus('error'); } // 设置通用错误消息 setGeneralRequestError(standardizedError.generalMessages); // 如果是表单场景,处理字段错误(依赖React Hook Form的setError) if (setError && standardizedError.fieldErrors.length > 0) { standardizedError.fieldErrors.forEach(err => { const transformedField = fieldNameTransformer(err.field); setError(transformedField, { type: 'server', message: err.message, }); }); } } }, [requestStatus, setError]); return { requestStatus, generalRequestError, handleRequest, }; };
在组件中使用示例
不管是表单提交还是普通更新请求,都能简化代码:
表单提交场景
import { useForm } from 'react-hook-form'; import api from '../utils/axios'; import { useApiRequest } from '../hooks/useApiRequest'; import { ACTIONS } from '../contexts/emailIntegrationContext'; const REQUEST_STATUS = { REQUESTING: 'requesting', INPUT: 'input', ERROR: 'error', SUCCESS: 'success', }; const YourFormComponent = ({ appUserConnect, emailIntegrationContext }) => { const { register, handleSubmit, setError } = useForm(); const { requestStatus, generalRequestError, handleRequest } = useApiRequest(setError); const onSubmit = handleSubmit(async (formData) => { await handleRequest( // 传入API调用函数 () => api.patch('end_point_data', formData), // 成功后的回调 (response) => { emailIntegrationContext.dispatch({ type: ACTIONS.UPDATE, id: appUserConnect.appUserConnectId, payload: response.data.payload, }); } ); }); return ( // 你的表单UI,根据requestStatus显示加载状态,generalRequestError显示通用错误 <form onSubmit={onSubmit}> {generalRequestError && <div className="error">{generalRequestError.join(', ')}</div>} {/* 表单输入项 */} <button type="submit" disabled={requestStatus === REQUEST_STATUS.REQUESTING}> {requestStatus === REQUEST_STATUS.REQUESTING ? '提交中...' : '提交'} </button> </form> ); };
普通更新请求场景(无表单)
import api from '../utils/axios'; import { useApiRequest } from '../hooks/useApiRequest'; const YourUpdateComponent = () => { const { requestStatus, generalRequestError, handleRequest } = useApiRequest(); const handleUpdate = async () => { await handleRequest( () => api.patch('some_update_endpoint', { data: 'xxx' }), (response) => { // 成功后的UI更新逻辑 console.log('更新成功', response.data); } ); }; return ( <div> {generalRequestError && <div className="error">{generalRequestError.join(', ')}</div>} <button onClick={handleUpdate} disabled={requestStatus === 'requesting'}> {requestStatus === 'requesting' ? '更新中...' : '更新'} </button> </div> ); };
关于第三方库
如果不想自己写,React Query(现在叫TanStack Query)也能帮你处理请求状态和错误,但它更偏向数据缓存,如果你只是需要错误和状态管理,上面的自定义方案更轻量,也更贴合你的API格式。
内容的提问来源于stack exchange,提问作者Burton
相关产品推荐
相关产品推荐

