Axios拦截器中含useDispatch的函数Dispatch失效问题求助
Axios拦截器中Redux Dispatch失效问题解决方案
问题原因
useDispatch是React Redux的Hook,仅能在React函数组件或自定义Hook的顶层调用,不能直接在普通JavaScript函数(比如你的addErrorToast)中使用——这违反了Hook的使用规则,导致dispatch无法正常执行。
可行解决方案
方案一:直接使用Redux Store实例
在项目初始化Redux store时导出实例,直接在拦截器相关函数中调用store.dispatch:
- 导出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, }, });
- 修改
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, }) ); };
- 保持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:
- 在根组件中监听事件:
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]); // ...其他组件逻辑 }
- 修改
addErrorToast函数触发事件:
const addErrorToast = () => { window.dispatchEvent(new Event('showErrorToast')); };
内容的提问来源于stack exchange,提问作者Test1234
相关产品推荐
相关产品推荐

