React Native Expo项目中axios.interceptors被多次调用是什么原因?
问题原因
- 核心原因是拦截器重复注册:你当前的请求拦截器注册逻辑写在了页面组件内部,React Native 页面切换时组件会反复挂载,每挂载一次就会给全局 axios 实例新增一个拦截器,发起请求时所有已注册的拦截器都会依次执行,自然会出现多次触发的情况。
- 你写的拦截器移除(eject)逻辑完全无效:一方面你是在拦截器的执行回调里才做移除操作,此时已经完成了多次注册,仅能移除最后一个注册的拦截器;另一方面就算本次移除了,下次组件重新挂载又会注册新的拦截器,无法从根源解决问题。
- 额外提个小问题:你响应拦截器的错误分支没有关闭 loading 状态,且错误日志打印的文案误写为请求拦截器的报错标识,后续可以顺便修正。
解决方案
- 全局统一注册拦截器,仅执行一次
单独新建 axios 配置文件(比如utils/request.js),把拦截器注册逻辑放在这个文件里,整个应用初始化时仅引入执行一次,避免重复注册。示例代码如下:
import axios from 'axios'; import * as SecureStore from 'expo-secure-store'; // 这里如果需要控制全局loading、处理401登出,引入对应的全局状态/全局方法即可 // 请求拦截器 全局仅注册一次 axios.interceptors.request.use( async (config) => { if (config.url === "login/login") { return config; } // 替换为你自己的全局loading开启逻辑,不要用组件内的state setGlobalLoading(true); const token = await SecureStore.getItemAsync('token'); console.log("Axios Call: " + config.url) if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { console.log('Error => axios.interceptors.request'); console.log(error); return Promise.reject(error); } ); // 响应拦截器 全局仅注册一次 axios.interceptors.response.use( (response) => { // 替换为你自己的全局loading关闭逻辑 setGlobalLoading(false); return response; }, (error) => { // 错误分支也要关闭loading,避免loading常驻 setGlobalLoading(false); if (error.response?.status === 401) { // 调用全局登出方法 authContext.signOut(); } console.log('Error => axios.interceptors.response'); console.log(error); return Promise.reject(error); } ); export default axios;
- 移除所有页面组件内的拦截器相关代码
所有页面发起请求时,直接导入上面封装好的 axios 实例即可,不要再在组件内写拦截器注册、eject 相关的逻辑。 - loading状态适配
如果你之前用的是组件内的setIsLoading来控制加载状态,要么改成全局状态管理(比如Zustand/Redux)来配合全局拦截器使用,要么直接在业务请求代码里单独控制页面级loading,不要把页面状态放到全局拦截器里处理。
内容的提问来源于stack exchange,提问作者Arti
相关产品推荐
相关产品推荐

