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

Axios拦截器中含useDispatch的函数Dispatch失效问题求助

Axios拦截器中Redux Dispatch失效问题解决方案

问题原因

useDispatch是React Redux的Hook,仅能在React函数组件或自定义Hook的顶层调用,不能直接在普通JavaScript函数(比如你的addErrorToast)中使用——这违反了Hook的使用规则,导致dispatch无法正常执行。

可行解决方案

方案一:直接使用Redux Store实例

在项目初始化Redux store时导出实例,直接在拦截器相关函数中调用store.dispatch:

  1. 导出Redux Store实例(假设store文件为store.js):
// store.js
import { configureStore } from '@reduxjs/toolkit';
import toastReducer from './features/toast/toastSlice';

export const store = configureStore({
  reducer: {
    toast: toastReducer,
  },
});
  1. 修改addErrorToast函数:
import { store } from './store';
import { addToast } from './features/toast/toastSlice';
import { FormattedMessage } from 'react-intl';

const addErrorToast = () => {
  store.dispatch(
    addToast({
      type: "error", // 原代码用了success,建议改为error匹配400错误场景
      msg: (
        <FormattedMessage
          id="notifications.error.400"
          defaultMessage="请求错误,请稍后重试!"
        />
      ),
      hasCloseIcon: false,
    })
  );
};
  1. 保持axios拦截器代码不变,直接调用修改后的addErrorToast即可。

方案二:将拦截器封装为自定义Hook

把拦截器初始化逻辑放到自定义Hook中,符合React Hook的使用规则:

import { useDispatch } from 'react-redux';
import { addToast } from './features/toast/toastSlice';
import { FormattedMessage } from 'react-intl';
import axios from 'axios';
import { useEffect } from 'react';

export const useAxiosInterceptor = () => {
  const dispatch = useDispatch();

  const addErrorToast = () => {
    dispatch(
      addToast({
        type: "error",
        msg: (
          <FormattedMessage
            id="notifications.error.400"
            defaultMessage="请求错误,请稍后重试!"
          />
        ),
        hasCloseIcon: false,
      })
    );
  };

  useEffect(() => {
    const token = getCookie(COOKIE_JWT_TOKEN);
    
    const requestInterceptor = axios.interceptors.request.use((config) => {
      config.performance = calculateTimes();
      config.timestamp = Date.now();
      return config;
    });
  
    const responseInterceptor = axios.interceptors.response.use(
      (response) => {
        if (response) {
          flightInfo = { ...flightInfo, ...response.data };
        }
        return Promise.resolve(response);
      },
      (error) => {
        if (error.response?.status === 400) {
          addErrorToast();
          window.location.href = `${window.location.origin}/app`;
        } 
        return Promise.reject(error);
      }
    );

    // 组件卸载时移除拦截器,避免内存泄漏
    return () => {
      axios.interceptors.request.eject(requestInterceptor);
      axios.interceptors.response.eject(responseInterceptor);
    };
  }, [dispatch]);
};

使用方式:在根组件(如App.js)中初始化拦截器:

import { useAxiosInterceptor } from './hooks/useAxiosInterceptor';

function App() {
  useAxiosInterceptor();

  // ...其他组件逻辑
}

方案三:通过自定义事件总线传递通知

在React组件中监听自定义事件,拦截器触发事件后由组件执行dispatch:

  1. 在根组件中监听事件:
import { useDispatch } from 'react-redux';
import { addToast } from './features/toast/toastSlice';
import { FormattedMessage } from 'react-intl';
import { useEffect } from 'react';

function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    const handleShowErrorToast = () => {
      dispatch(
        addToast({
          type: "error",
          msg: (
            <FormattedMessage
              id="notifications.error.400"
              defaultMessage="请求错误,请稍后重试!"
            />
          ),
          hasCloseIcon: false,
        })
      );
    };

    window.addEventListener('showErrorToast', handleShowErrorToast);
    return () => {
      window.removeEventListener('showErrorToast', handleShowErrorToast);
    };
  }, [dispatch]);

  // ...其他组件逻辑
}
  1. 修改addErrorToast函数触发事件:
const addErrorToast = () => {
  window.dispatchEvent(new Event('showErrorToast'));
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:31:18