如何在Axios拦截器中使用useSelector?Hook调用报错求助
解决Axios拦截器中使用useSelector的Hook调用错误
错误原因
useSelector 是React Hook,必须满足两个核心规则:
- 只能在函数组件或自定义Hook的顶层作用域调用
- 不能在普通工具函数、循环、条件判断中调用
你现在在普通函数 axiosRequest 里直接使用 useSelector,违反了Hook规则,所以触发 Invalid hook call 错误。
解决方案一:直接访问Redux Store实例
如果你的Redux Store是单独创建并导出的(比如store.ts中导出了store对象),可以直接调用store.getState()获取状态,无需使用Hook:
import store from './path/to/your/store'; // 导入你的Redux Store实例 import { currentUserToken } from './path/to/your/selectors'; function axiosRequest(request: AxiosRequestConfig): AxiosRequestConfig | Promise<AxiosRequestConfig> { const state = store.getState(); const currentToken = currentUserToken(state); // 直接调用selector函数传入state request.headers["X-Auth-token"] = currentToken; return request; }
这种方式简单直接,适合在非组件环境中获取Redux状态。
解决方案二:在组件中动态更新Axios默认Headers
将token的获取放在React组件中,利用useSelector监听token变化,实时更新Axios实例的默认请求头:
// 根组件(如App.tsx) import { useSelector, useEffect } from 'react-redux'; import { instance } from './path/to/your/axios-instance'; import { currentUserToken } from './path/to/your/selectors'; function App() { const currentToken = useSelector(currentUserToken); // 每次token变化时更新Axios默认请求头 useEffect(() => { instance.defaults.headers.common['X-Auth-token'] = currentToken; }, [currentToken, instance]); return ( // 你的组件内容 ); }
此时拦截器无需再处理token,直接返回请求即可:
function axiosRequest(request: AxiosRequestConfig): AxiosRequestConfig | Promise<AxiosRequestConfig> { return request; }
这种方式更贴合React数据流,将状态管理逻辑限制在组件内部。
解决方案三:用自定义Hook初始化拦截器
创建自定义Hook,在Hook内部使用useSelector获取token,并动态添加/移除拦截器,完全符合Hook规则:
import { useSelector, useEffect } from 'react-redux'; import { AxiosInstance } from 'axios'; import { currentUserToken } from './path/to/your/selectors'; function useAxiosInterceptor(instance: AxiosInstance) { const currentToken = useSelector(currentUserToken); useEffect(() => { // 添加请求拦截器 const interceptorId = instance.interceptors.request.use( (request) => { request.headers["X-Auth-token"] = currentToken; return request; }, (error) => Promise.reject(error?.message || error) ); // 组件卸载时移除拦截器,避免内存泄漏 return () => { instance.interceptors.request.eject(interceptorId); }; }, [instance, currentToken]); }
然后在根组件中调用这个Hook:
// App.tsx import { instance } from './path/to/your/axios-instance'; import { useAxiosInterceptor } from './path/to/your/hook'; function App() { useAxiosInterceptor(instance); return ( // 你的组件内容 ); }
这种方式既符合Hook规则,又能保证token变化时拦截器自动更新。
内容的提问来源于stack exchange,提问作者Arthur788
相关产品推荐
相关产品推荐

