React中Toast显示错误代码而非实际消息的问题排查
问题描述
调用用户注册API后,无法正常显示错误或成功消息。当用户已存在时,API返回User already exists,但Toast却显示Request failed with status code 409——尽管开发者工具里能看到实际的响应内容。以下是相关的Redux异步action代码和React组件代码,无法定位问题出在API返回处理还是组件捕获逻辑上。
相关代码
Redux异步Action代码
export const registerUser = (payload: RegisterPayload) => async (dispatch: AppDispatch) => { dispatch(registerStart()); try { const response = await axiosClient.post('/register', payload); let successMessage = 'Operation successful'; if (response.data?.detail) { successMessage = response.data.detail .map((msg: string) => { const message = msg; const commaIndex = message.indexOf(':'); // 检查是否存在冒号并裁剪消息 if (commaIndex !== -1) { return message.substring(commaIndex + 2); } return message; }) .join(', '); } dispatch(registerSuccess(response.data)); dispatch(showToast({ message: successMessage, type: 'success' })); return { success: true, data: response.data, message: successMessage }; } catch (error: any) { let errorMessage = 'An error occurred'; // 处理FastAPI的detail列表错误 if (error.response && Array.isArray(error.response.data?.detail)) { // 从detail列表提取消息 errorMessage = error.response.data.detail .map((err: { msg: string }) => { const errorMsg = err.msg; const commaIndex = errorMsg.indexOf(', '); // 检查是否存在逗号并裁剪消息 if (commaIndex !== -1) { return errorMsg.substring(commaIndex + 2); } return errorMsg; }) .join(', '); } else if (error.response?.data?.error) { errorMessage = error.response.data.error; } else if (error.message) { errorMessage = error.message; } dispatch(registerFailure(errorMessage)); dispatch(showToast({ message: errorMessage, type: 'error' })); return { success: false, message: errorMessage }; } };
React组件代码
const initialValues={ firstname: '', lastname: '', username: '', email: '', password: '', changepassword: '', } const UserRegistration: React.FC = () => { const dispatch = useAppDispatch(); const [errorMessage, setErrorMessage] = useState<string | null>(null); const [successMessage, setSuccessMessage] = useState<string | null>(null); const { loading } = useAppSelector((state) => state.user); const handleApiResponse = (result: { success: boolean; message?: string; data?: any }) => { if (!result.success) { const errorMessage = result.message ?? 'An unknown error occurred'; setErrorMessage(errorMessage); dispatch(showToast({ message: errorMessage, type: 'error' })); } else { const successMessage = result.message ?? 'Operation successful'; setSuccessMessage(successMessage); dispatch(showToast({ message: successMessage, type: 'success' })); } }; const handleSubmit = async (values: typeof initialValues, { setSubmitting }: { setSubmitting: (isSubmitting: boolean) => void }) => { const apiValues: RegisterPayload = { first_name: values.firstname, last_name: values.lastname, username: values.username, email: values.email, password: values.password, password_confirm: values.changepassword, }; try { const apiResponse = await dispatch(registerUser(apiValues)); handleApiResponse(apiResponse); } catch (error: any) { if (error.message) handleApiResponse(error); } finally { setSubmitting(false); } }; const formik = useFormik({ initialValues, validationSchema: UserRegistrationSchema, onSubmit: handleSubmit, }); return ( // 表单代码省略 ) }; export default UserRegistration;
问题定位与修复
1. 核心问题:错误响应的判断逻辑不全
当用户已存在时,API返回的detail是字符串类型,但你的Redux Action只处理了detail为数组的情况,导致匹配不到正确的分支,最终走了else if (error.message),使用了axios默认的错误提示Request failed with status code 409。
修复Redux Action的错误处理逻辑
修改catch块,增加对字符串类型detail的判断:
catch (error: any) { let errorMessage = 'An error occurred'; if (error.response) { // 处理FastAPI的detail:兼容数组和字符串两种格式 if (error.response.data?.detail) { if (Array.isArray(error.response.data.detail)) { // 数组类型detail,提取msg内容 errorMessage = error.response.data.detail .map((err: { msg: string }) => { const errorMsg = err.msg; const commaIndex = errorMsg.indexOf(', '); if (commaIndex !== -1) { return errorMsg.substring(commaIndex + 2); } return errorMsg; }) .join(', '); } else { // 字符串类型detail,直接使用 errorMessage = error.response.data.detail; } } else if (error.response.data?.error) { errorMessage = error.response.data.error; } } else if (error.message) { // 处理无响应的网络错误 errorMessage = error.message; } dispatch(registerFailure(errorMessage)); dispatch(showToast({ message: errorMessage, type: 'error' })); return { success: false, message: errorMessage }; }
2. 次要问题:组件中冗余的Toast调用
你的Redux Action已经调用了showToast,但组件的handleApiResponse又重复调用了一次,会导致Toast重复显示。同时,handleSubmit中的try/catch是多余的——因为Action内部已经捕获了错误并返回结果,不会抛出异常。
修复React组件的冗余逻辑
// 修改handleApiResponse,移除重复的Toast调用 const handleApiResponse = (result: { success: boolean; message?: string; data?: any }) => { if (!result.success) { const errorMessage = result.message ?? 'An unknown error occurred'; setErrorMessage(errorMessage); } else { const successMessage = result.message ?? 'Operation successful'; setSuccessMessage(successMessage); } }; // 修改handleSubmit,移除多余的try/catch const handleSubmit = async (values: typeof initialValues, { setSubmitting }: { setSubmitting: (isSubmitting: boolean) => void }) => { const apiValues: RegisterPayload = { first_name: values.firstname, last_name: values.lastname, username: values.username, email: values.email, password: values.password, password_confirm: values.changepassword, }; const apiResponse = await dispatch(registerUser(apiValues)); handleApiResponse(apiResponse); setSubmitting(false); };
内容的提问来源于stack exchange,提问作者Jazzman
相关产品推荐
相关产品推荐

