为何将axiosPrivate置于自定义Hook内时Axios拦截器有时失效?
Axios拦截器在自定义Hook内部创建实例时部分失效的原因
问题背景
原本将Axios实例axiosPrivate定义在自定义Hook外部时,拦截器工作正常:
import axios from 'axios'; import { useDispatch } from 'react-redux'; const axiosPrivate = axios.create({ baseURL: 'http://localhost:8080' }); export default useAxiosPrivate = () => { const dispatch = useDispatch(); useEffect(() => { const responseIntercept = axiosPrivate.interceptors.response.use( response => response, async (error) => { const prevRequest = error?.config; if (error.response?.status === 401 && error.response.data?.code === 'AccessTokenExpired' && !prevRequest.sent) { prevRequest.sent = true; const { refreshToken } = await getData(); return axios.post('http://localhost:8080/auth/refresh-token', { refreshToken }) .then(async (_) => { return axiosPrivate(prevRequest); }) .catch(async (error) => { dispatch(login({ name: '', id: '' })); return Promise.reject(error); }); } return Promise.reject(error); } ); return () => { axiosPrivate.interceptors.response.eject(responseIntercept); } }, []) return axiosPrivate; }
之后尝试将axiosPrivate移至自定义Hook内部:
export default useAxiosPrivate = () => { const axiosPrivate = axios.create({ baseURL: 'localhost:8080' }); const dispatch = useDispatch(); // 后续拦截器逻辑同原代码... }
此时出现部分组件中拦截器正常工作,另一部分组件中拦截器完全失效的现象。
原因解析
- 每次调用Hook都会生成全新的Axios实例:把
axiosPrivate放在Hook内部后,每个调用useAxiosPrivate的组件都会得到一个独立的Axios实例。拦截器是绑定在单个实例上的,只有那些在useEffect(拦截器挂载逻辑在这里)执行完成后才发起请求的组件,其对应的实例拦截器才会生效;如果组件在useEffect执行前就发起请求,此时拦截器还没挂载到这个新实例上,就会出现拦截器“失效”的情况。 - 组件渲染时机导致拦截器挂载时机不一致:不同组件的渲染顺序和生命周期阶段有差异,有些组件可能在Hook的
useEffect执行前就调用Axios实例发请求,这时实例上还没有绑定拦截器,请求直接发出,不会触发拦截逻辑;而另一些组件在useEffect执行完成后才发请求,拦截器已经挂载,所以能正常工作。 - 原代码的核心优势:原代码中
axiosPrivate是全局单例,所有组件共享同一个实例,拦截器挂载后所有请求都会走这个实例的拦截逻辑,不存在挂载时机不一致的问题。
内容的提问来源于stack exchange,提问作者Bruno Nobre
相关产品推荐
相关产品推荐

