You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否应使用state、ref或useMemo存储含授权拦截器的Axios实例?

解决方案:动态更新Axios请求头,无需重建实例

你之前踩坑的核心原因

  • useMemo方案:token变化时重建实例,但异步操作可能捕获到旧实例(实例切换存在时序差),导致请求携带过期token。
  • useRef方案:实例存在ref中时,更新ref不会触发组件重渲染,组件闭包里捕获的还是旧的ref值,依然会调用旧实例。
  • 观察者模式:即使通知更新ref,组件如果已在闭包里保存了旧实例引用,还是会出现旧实例被调用的情况。

推荐方案:固定Axios实例,动态注入最新token

根本不需要重建实例,也不用把实例存进useState,只需要让Axios的请求拦截器每次都能拿到最新的token即可。具体实现分三步:

1. 创建全局Axios实例,用可变变量存最新token

// axiosInstance.js
import axios from 'axios';

// 只创建一次Axios实例,复用全局配置
const axiosInstance = axios.create({
  baseURL: 'https://your-api-domain.com',
  timeout: 10000,
});

// 用可变变量存储最新token,规避闭包陷阱
let currentAuthToken = null;

// 对外暴露更新token的方法
export function updateAuthToken(token) {
  currentAuthToken = token;
}

// 请求拦截器每次请求都会执行,动态注入最新token
axiosInstance.interceptors.request.use((config) => {
  if (currentAuthToken) {
    config.headers.Authorization = `Bearer ${currentAuthToken}`;
  }
  return config;
});

export default axiosInstance;

2. 在AuthContext中同步token到Axios实例

// AuthContext.js
import { createContext, useContext, useState, useEffect } from 'react';
import { updateAuthToken } from './axiosInstance';

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [authorization, setAuthorization] = useState(null);

  // 每次token变化时,同步到Axios实例的token变量
  useEffect(() => {
    updateAuthToken(authorization);
  }, [authorization]);

  return (
    <AuthContext.Provider value={{ authorization, setAuthorization }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

3. 组件/Store中直接复用Axios实例

不管是在组件里还是状态管理库中,直接导入axiosInstance使用即可,每次请求都会自动带上最新的Authorization头:

// 组件中使用示例
import axiosInstance from './axiosInstance';

async function fetchUserData() {
  try {
    const res = await axiosInstance.get('/user/profile');
    console.log(res.data);
  } catch (err) {
    console.error(err);
  }
}

其他方案的优缺点分析

  • 把Axios实例存进useState:token变化会触发组件重渲染,所有用到该实例的组件都会跟着更新,带来不必要的性能损耗,完全没必要。
  • 每次请求新建Axios实例:虽然能拿到当前token,但每次创建实例会重复初始化配置,代码冗余且有额外性能开销,不利于拦截器、全局配置的复用。

内容的提问来源于stack exchange,提问作者Archimedes Trajano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:11:46