You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Redux中如何实现Axios API全局错误处理?

React-Redux 全局API错误处理方案

针对你遇到的重复处理API错误、无法在Reducer中跳转页面的问题,以下是两种高效的全局处理方案,同时解决类型错误问题:

方案一:自定义Redux中间件(推荐)

利用Redux中间件拦截所有createAsyncThunk的错误action,直接在中间件中处理页面跳转,无需组件重复逻辑。

步骤1:在AsyncThunk中传递错误详情

在所有API请求的createAsyncThunk中,用rejectWithValue携带错误状态码和信息:

import { createAsyncThunk } from '@reduxjs/toolkit';

// TypeScript用户可提前定义错误类型
interface ApiError {
  status: number;
  message: string;
}

export const fetchData = createAsyncThunk(
  'data/fetch',
  async (params, { rejectWithValue }) => {
    try {
      const response = await fetch('/api/data');
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ message: response.statusText }));
        // 传递状态码和错误信息
        return rejectWithValue<ApiError>({ status: response.status, ...errorData });
      }
      return response.json();
    } catch (err) {
      // 捕获网络错误(如后端未运行),标记为503状态
      return rejectWithValue<ApiError>({ status: 503, message: '服务暂不可用' });
    }
  }
);

步骤2:编写错误处理中间件

中间件可直接访问路由跳转方法,拦截所有rejected状态的AsyncThunk action:

// middleware/errorHandling.js
export const errorHandlingMiddleware = (navigate) => (store) => (next) => (action) => {
  // 匹配所有createAsyncThunk的错误action
  if (action.type.endsWith('/rejected')) {
    const { status } = action.payload || {};
    switch (status) {
      case 404:
        navigate('/404');
        break;
      case 503:
        navigate('/maintenance');
        break;
      // 可扩展其他全局错误逻辑
      default:
        // 非全局处理的错误,可留到组件单独处理
        break;
    }
  }
  return next(action);
};

步骤3:将路由方法注入Store

在App组件中获取navigate实例,传递给Store配置:

// App.jsx
import { useNavigate } from 'react-router-dom';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import dataReducer from './slices/dataSlice';
import { errorHandlingMiddleware } from './middleware/errorHandling';

function App() {
  const navigate = useNavigate();
  const store = configureStore({
    reducer: { data: dataReducer },
    middleware: (getDefault) => getDefault().concat(errorHandlingMiddleware(navigate))
  });

  return (
    <Provider store={store}>
      {/* 路由组件 */}
    </Provider>
  );
}

方案二:全局错误监听组件

通过React组件监听Redux中的全局错误状态,触发页面跳转,适合不想修改中间件的场景。

步骤1:创建全局错误Slice

统一存储API错误状态:

// slices/globalErrorSlice.js
import { createSlice, isRejectedAction } from '@reduxjs/toolkit';

const initialState = { status: null, message: '' };

const globalErrorSlice = createSlice({
  name: 'globalError',
  initialState,
  reducers: {
    clearGlobalError: (state) => {
      state.status = null;
      state.message = '';
    }
  },
  extraReducers: (builder) => {
    // 监听所有AsyncThunk的错误action
    builder.addMatcher(isRejectedAction, (state, action) => {
      if (action.payload?.status) {
        state.status = action.payload.status;
        state.message = action.payload.message || '请求失败';
      }
    });
  }
});

export const { clearGlobalError } = globalErrorSlice.actions;
export default globalErrorSlice.reducer;

步骤2:编写全局错误处理组件

监听错误状态,自动跳转页面:

// components/GlobalErrorHandler.jsx
import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { clearGlobalError } from '../slices/globalErrorSlice';

const GlobalErrorHandler = () => {
  const { status } = useSelector(state => state.globalError);
  const navigate = useNavigate();
  const dispatch = useDispatch();

  useEffect(() => {
    if (!status) return;

    switch (status) {
      case 404:
        navigate('/404');
        break;
      case 503:
        navigate('/maintenance');
        break;
    }

    // 跳转后清除错误状态,避免重复触发
    return () => dispatch(clearGlobalError());
  }, [status, navigate, dispatch]);

  return null; // 无需渲染DOM
};

export default GlobalErrorHandler;

步骤3:在App中注册组件

将全局错误组件放在路由和Provider内部:

// App.jsx
import { Provider } from 'react-redux';
import { store } from './store'; // 需包含globalErrorReducer
import { BrowserRouter } from 'react-router-dom';
import GlobalErrorHandler from './components/GlobalErrorHandler';

function App() {
  return (
    <Provider store={store}>
      <BrowserRouter>
        <GlobalErrorHandler />
        {/* 其他路由组件 */}
      </BrowserRouter>
    </Provider>
  );
}

类型错误解决技巧

如果使用TypeScript,确保为createAsyncThunk的rejectValue指定类型(如方案一中的ApiError接口),同时在中间件或Slice中明确action的类型,让TypeScript自动推断payload结构,避免类型不匹配的问题。

内容的提问来源于stack exchange,提问作者wojg21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 21:35:33