Axios拦截器重复执行问题:多组件用自定义Hook日志重复
问题根源与解决方案
你的问题核心在于:每次调用useAxiosPrivate时,都给同一个Axios实例重复添加了请求拦截器,而非每个Hook实例对应独立的拦截器组。
具体原因
如果你的useAxiosPrivate复用了同一个全局Axios实例(比如通过axios.create()创建的实例被多个Hook共享),每次Hook初始化时调用instance.interceptors.request.use(),都会往该实例的拦截器队列中新增一个拦截器。随着你在更多组件中使用这个Hook,拦截器数量会不断累积,导致单次请求触发所有已添加的拦截器,日志打印次数自然递增。
验证方法
可以在添加拦截器前打印拦截器队列长度,确认累积情况:
console.log('当前请求拦截器数量:', instance.interceptors.request.handlers.length);
你会发现每次调用useAxiosPrivate时,这个数字都会+1。
解决办法
方案1:每个Hook实例创建独立Axios实例
在useAxiosPrivate内部每次都生成新的Axios实例,确保拦截器完全独立:
import { useMemo } from 'react'; import axios from 'axios'; const useAxiosPrivate = () => { const instance = useMemo(() => { const axiosInstance = axios.create({ baseURL: '/api' }); // 给当前实例添加专属拦截器 axiosInstance.interceptors.request.use( (config) => { console.log('请求地址:', config.url); // 处理token逻辑 return config; }, (error) => Promise.reject(error) ); return axiosInstance; }, []); return instance; };
方案2:添加拦截器时做去重检查
给拦截器添加唯一标识,确保同一类型的拦截器只添加一次:
import { useEffect, useRef } from 'react'; import axios from 'axios'; const useAxiosPrivate = () => { const instance = useRef(axios.create({ baseURL: '/api' })).current; const hasInterceptor = useRef(false); useEffect(() => { if (!hasInterceptor.current) { instance.interceptors.request.use( (config) => { console.log('请求地址:', config.url); // 处理token逻辑 return config; }, (error) => Promise.reject(error) ); hasInterceptor.current = true; } }, [instance]); return instance; };
方案3:组件卸载时移除拦截器
利用useEffect的清理函数,在组件卸载时移除对应的拦截器,避免累积:
import { useEffect, useRef } from 'react'; import axios from 'axios'; const useAxiosPrivate = () => { const instance = useRef(axios.create({ baseURL: '/api' })).current; const interceptorId = useRef(null); useEffect(() => { // 添加拦截器并保存ID interceptorId.current = instance.interceptors.request.use( (config) => { console.log('请求地址:', config.url); // 处理token逻辑 return config; }, (error) => Promise.reject(error) ); // 组件卸载时移除拦截器 return () => { if (interceptorId.current) { instance.interceptors.request.eject(interceptorId.current); } }; }, [instance]); return instance; };
内容的提问来源于stack exchange,提问作者Joao
相关产品推荐
相关产品推荐

