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

React中从local storage获取token传入axios请求的最佳实践是什么?

推荐实现方案

以下是从可维护性、复用性角度出发的优化方案,按优先级排列:


1. 第一步:抽离公共工具方法解决重复代码问题

把重复的getTokenFromLocalStorage方法单独抽离为公共工具函数,存放在src/utils/auth.js这类公共工具目录下,所有需要的服务直接导入使用即可:

// src/utils/auth.js
export const getTokenFromLocalStorage = () => {
  try {
    const token = localStorage.getItem("token");
    console.log("the token is -> " + token);
    return token ?? undefined;
  } catch(err) {
    return undefined;
  }
}

之后在AuthService、TicketService里直接导入这个函数使用,不用每个类都单独实现一遍。


2. 第二步:用axios拦截器统一注入token,彻底避免每个请求单独配置header

创建全局通用的自定义axios实例,统一配置baseURL、请求拦截器自动注入token,不用每个接口请求都手动写header配置:

// src/utils/request.js
import axios from 'axios'
import { getTokenFromLocalStorage } from './auth'

const request = axios.create({
  baseURL: API_BASE_URL,
  timeout: 10000
})

// 请求拦截器:自动注入token
request.interceptors.request.use(
  config => {
    const token = getTokenFromLocalStorage()
    if (token) {
      // 适配不同接口的header要求
      if (config.url === '/authenticate') {
        config.headers.token = token
      } else {
        config.headers.Authorization = `Bearer ${token}`
      }
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 还可以加响应拦截器统一处理token过期、401权限不足的情况,自动跳转到登录页
request.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) {
      window.location.href = '/login'
    }
    return Promise.reject(error)
  }
)

export default request

之后两个Service里直接用这个封装好的axios实例发请求即可,不用再处理token和header:

// AuthService 简化后
import request from '@/utils/request'
export const validateToken = () => {
  return request.get("/authenticate")
    .catch((error) => {
      console.log("failed to validate token" + error);
      return null;
    });
}

// TicketService 简化后
import request from '@/utils/request'
export const getTickets = () => {
  console.log("getting tickets!");
  console.log("Environment variable: " + process.env.NODE_ENV);
  return request.get("/tickets")
    .catch((error) => {
      console.log("failed to get tickets" + error);
    });
}

3. 第三步:统一鉴权逻辑,避免每个组件单独写校验

如果项目用的是React Router,可以用路由守卫/高阶组件统一包裹需要鉴权的路由,所有需要登录的页面都会自动走token校验,不用每个组件的componentDidMount里都重复写校验逻辑:

// 鉴权高阶组件示例
import { useEffect } from 'react'
import { validateToken } from '@/services/AuthService'

const withAuth = (Component) => {
  return (props) => {
    useEffect(() => {
      const checkAuth = async () => {
        const res = await validateToken()
        const token = localStorage.getItem('token')
        if (!res || !token) {
          props.history.push('/login')
        }
      }
      checkAuth()
    }, [props.history])

    return <Component {...props} />
  }
}

// 路由配置时直接包裹需要鉴权的组件即可
<Route path="/tickets" component={withAuth(TicketsComponent)} />

原有代码的小问题修复

  • 原来的then("did it")、then("yessssss")写法是错误的,then的参数需要是函数,否则会直接透传上一步的返回值,没有实际作用,建议删除
  • 可以在校验token前先判断本地有没有token,如果没有直接跳登录,不用发无效的校验请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:27:04