在Axios配置文件调用React Hook报错,如何正确获取Auth Context的token?
错误原因
该报错由React Hook调用规则限制触发:React Hook仅允许在React函数组件顶层、自定义React Hook顶层调用,你在普通JS模块顶层执行useAuth()不属于合法调用场景,因此抛出异常。
此外就算绕过语法报错,模块加载阶段创建的axios实例无法同步后续更新的token值,也会出现请求鉴权失败的问题。
最优实现方案
方案1:Token持久化+请求拦截器(最通用,推荐度最高)
无需修改现有请求调用逻辑,自动同步最新token,适配绝大多数业务场景:
- 调整
AuthContext.js,登录时同步持久化存储token:
import React, { useContext, createContext, useState } from "react"; const AuthContext = createContext(); export function useAuth() { return useContext(AuthContext); } export function AuthProvider({ children }) { // 初始化时从本地存储读取token,刷新页面不会丢失登录态 const [currentToken, setCurrentToken] = useState(localStorage.getItem('auth_token') || ""); const [isAuth, setIsAuth] = useState(!!localStorage.getItem('auth_token')); function login(token) { setCurrentToken(token); setIsAuth(true); localStorage.setItem('auth_token', token); } function logout() { setCurrentToken(""); setIsAuth(false); localStorage.removeItem('auth_token'); } const value = { login, logout, currentToken, isAuth, }; return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; }
- 调整
AxiosConfig.js,移除顶层Hook调用,添加请求拦截器动态注入token:
import axios from "axios"; const axiosInstance = axios.create({ baseURL: "http://127.0.0.1:8000", headers: { "Content-type": "application/json", }, }); // 每次发请求前自动读取最新token注入请求头 axiosInstance.interceptors.request.use( (config) => { const token = localStorage.getItem('auth_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); export default axiosInstance;
后续业务组件直接导入axiosInstance发送请求即可,无需额外配置。
方案2:自定义请求Hook(适合高安全要求场景,token不落地本地存储)
如果token属于高敏感信息不允许存在本地存储,可以通过封装自定义Hook符合调用规则,仅在内存中持有token:
- 调整
AxiosConfig.js,仅导出基础axios实例:
import axios from "axios"; export const baseAxios = axios.create({ baseURL: "http://127.0.0.1:8000", headers: { "Content-type": "application/json", }, });
- 新增自定义Hook文件
useAxios.js:
import { useMemo } from "react"; import { baseAxios } from "./AxiosConfig"; import { useAuth } from "./AuthContext"; export function useAxios() { const { currentToken } = useAuth(); // token变化时自动更新实例配置 const axiosInstance = useMemo(() => { baseAxios.defaults.headers.common['Authorization'] = currentToken ? `Bearer ${currentToken}` : ''; return baseAxios; }, [currentToken]); return axiosInstance; }
- 业务组件内调用示例:
import { useAxios } from './useAxios'; function BusinessComponent() { const axios = useAxios(); const fetchData = async () => { const res = await axios.get('/api/your/interface'); // 处理返回结果 } return <button onClick={fetchData}>发起请求</button> }
内容的提问来源于stack exchange,提问作者Fillah Firdausyah
相关产品推荐
相关产品推荐

