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

如何在React的非组件普通类中使用Context获取存储的鉴权token

核心问题说明

  1. 你当前的AuthContextProvider仅向Context注入了isAuthenticated和toggleAuth两个值,userToken、userId等字段根本没有对外暴露,就算是React组件也无法从Context中读取到这些值。
  2. static contextType是React专门为React类组件提供的Context读取能力,你写的MediaService是普通JS类,不属于React组件体系,自然不具备读取Context的能力,this.context必然是undefined。

第一步:先修复AuthContext配置

首先修正Context的对外暴露字段,否则后续所有读取操作都会失效:

import React, { useState, createContext, useEffect } from 'react';
import loginService from '../service/LoginService';
import axios from 'axios';

export const AuthContext = createContext();

const AuthContextProvider = (props) => {
    const [isAuthenticated, setIsAuthenticated] = useState(false);
    const [userToken, setUserToken] = useState("");
    const [userId, setUserId] = useState("");
    const [userName, setUserName] = useState("");

    const toggleAuth = () => {
        if (!isAuthenticated) {
            setUserToken(loginService.getUserToken());
            setUserId(loginService.getUserId());
            setUserName(loginService.getUserName());
            setIsAuthenticated(true);
        } else {
            setUserToken(null);
            setUserId(null);
            setUserName(null);
            setIsAuthenticated(false);
        }
    }

    // 补充缺失的暴露字段
    return (
        <AuthContext.Provider value={{ 
            isAuthenticated, 
            toggleAuth,
            userToken,
            userId,
            userName 
        }}>
            {props.children}
        </AuthContext.Provider>
    );
}

export default AuthContextProvider;

第二步:根据需求选择解耦方案

以下两种方案都可以实现MediaService和React组件体系的解耦,按需选择即可:

方案1:参数透传(彻底解耦,推荐)

该方案下MediaService完全不需要感知React、Context的存在,所有依赖参数从外部传入,可复用性最高。

  • 修改MediaService代码:
import axios from 'axios';

class MediaService {
    galleryItems = [];

    constructor() {
        this.galleryItems = [];
    }

    // 新增token入参,注意原代码的Bearer拼写错误,不是Barier
    addItem = (item, token) => {
        axios.post("http://localhost:8080/image", item, {
            headers: {
                "Authorization": `Bearer ${token}`
            }
        })
        .then((response) => {
            item.id = response.data.id;
            this.galleryItems.push(item);
        }).catch((err) => {
            console.error(err);
        });
    }
}

export default new MediaService(); // 导出单例直接使用
  • 组件内调用方式:
import { useContext } from 'react';
import { AuthContext } from '你的AuthContext路径';
import mediaService from '你的MediaService路径';

function GalleryComponent() {
    // 仅在调用方组件读取Context
    const { userToken } = useContext(AuthContext);
    
    const handleUpload = (item) => {
        // 调用时透传token即可
        mediaService.addItem(item, userToken);
    }

    // 其余组件逻辑省略
}

方案2:Axios全局拦截器自动注入Token

适合项目请求量较大,不想每个方法都重复传token的场景

  • 在AuthContextProvider中新增token监听逻辑,更新axios全局配置:
// 在AuthContextProvider中补充useEffect逻辑
const AuthContextProvider = (props) => {
    // 原有state、toggleAuth逻辑不变
    
    // 新增:监听token变化,自动更新全局请求头
    useEffect(() => {
        if (userToken) {
            axios.defaults.headers.common['Authorization'] = `Bearer ${userToken}`;
        } else {
            delete axios.defaults.headers.common['Authorization'];
        }
    }, [userToken])

    // 原有return逻辑不变
}
  • 此时MediaService完全不需要处理token相关逻辑:
class MediaService {
    galleryItems = [];

    constructor() {
        this.galleryItems = [];
    }

    addItem = (item) => {
        // 不需要手动加headers,axios会自动携带全局配置的token
        axios.post("http://localhost:8080/image", item)
        .then((response) => {
            item.id = response.data.id;
            this.galleryItems.push(item);
        }).catch((err) => {
            console.error(err);
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:36:05