使用SWR Mutation+Axios+Next.js时出现未处理运行时AxiosError
解决SWR Mutation结合Axios在Next.js中触发错误模态框的问题
问题背景
使用SWR Mutation结合Axios实现Next.js登录功能时,明明接口已有响应,却会弹出Next.js的错误模态框;改用Fetch API实现则无此问题。相关代码如下:
fetch.ts
export const loginFetch = async ( url, { arg } ) => { try { // with fetch no problem but with axios show this modal next error const data = await BASE_URL.post<APIAuthLogin>(url, arg); return data; } }
form.tsx
const { trigger, error } = useMutation("/auth/login", loginFetch); async function onLogin(datos: AuthLogin) { await trigger(datos); }
问题根源
- Axios与Fetch的错误处理逻辑差异:Axios默认会对非2xx状态码的响应抛出异常,而Fetch API不会——它需要开发者手动通过
response.ok判断请求是否成功。当登录接口返回401(账号密码错误)这类非2xx状态码时,Axios会直接抛出错误,被SWR Mutation捕获后触发Next.js的错误边界。 - 缺少错误捕获逻辑:当前
loginFetch的try块没有对应的catch处理,导致Axios抛出的错误直接向上传递,触发全局错误模态框。 - 返回值结构不一致:Axios返回的是包含
data、status等字段的完整响应对象,而Fetch通常返回解析后的纯数据,这也可能导致SWR处理数据时的行为差异。
解决方案
方案1:添加错误捕获并对齐Fetch返回格式
修改fetch.ts中的loginFetch函数,捕获Axios错误并提取纯数据返回,和Fetch的行为对齐:
export const loginFetch = async (url, { arg }) => { try { const response = await BASE_URL.post<APIAuthLogin>(url, arg); // 返回Axios响应中的纯数据,和Fetch返回格式一致 return response.data; } catch (error) { // 区分响应错误和网络错误,自定义错误信息 if (error.response) { // 接口有响应但状态码非2xx,抛出包含响应数据的错误 throw new Error(JSON.stringify(error.response.data)); } else { // 处理网络异常等情况 throw new Error(error.message); } } };
方案2:修改Axios配置,禁用非2xx状态码拦截
如果希望Axios和Fetch一样不对非2xx状态码抛出错误,可以修改Axios实例配置:
// 创建BASE_URL实例时添加配置 const BASE_URL = axios.create({ // ...其他配置 validateStatus: (status) => { // 所有状态码都视为成功,不抛出错误 return true; } });
之后在loginFetch中手动判断状态码:
export const loginFetch = async (url, { arg }) => { const response = await BASE_URL.post<APIAuthLogin>(url, arg); // 手动判断状态码,非2xx则抛出错误 if (response.status >= 400) { throw new Error(JSON.stringify(response.data)); } return response.data; };
方案3:组件内捕获错误,避免触发全局错误边界
在form.tsx的登录函数中直接捕获错误,用自定义逻辑处理而非触发Next.js全局错误模态框:
async function onLogin(datos: AuthLogin) { try { await trigger(datos); } catch (error) { // 自定义错误处理,比如显示本地错误提示 console.error('登录失败:', error); // setLoginError(error.message); // 可结合状态显示错误信息 } }
内容的提问来源于stack exchange,提问作者vigilio
相关产品推荐
相关产品推荐

