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

解决Cannot read properties of null (reading 'user')报错 实现先登录再读localStorage token

问题根源

你代码中的TOKEN变量在requestMethod.js模块被引入时就会立即执行localStorage读取逻辑,此时用户尚未完成登录,localStorage.getItem('persist:root')返回值为null,后续读取null.user就会触发Cannot read properties of null (reading 'user')报错。

修复步骤

1. 重构requestMethod.js,使用请求拦截器动态获取Token

不要在axios实例初始化时就把Token写死在header中,改为每次发起鉴权请求前动态读取Token,同时增加判空逻辑避免未登录时的解析报错:

import axios from 'axios'

const BASE_URL = 'http://localhost:5000/api'

// 公共请求实例,无需携带Token,用于登录等公开接口
export const publicRequest = axios.create({
  baseURL: BASE_URL,
})

// 鉴权请求实例,通过拦截器动态注入Token
export const userRequest = axios.create({
  baseURL: BASE_URL,
})

// 新增请求拦截器
userRequest.interceptors.request.use(
  (config) => {
    const persistRoot = localStorage.getItem('persist:root')
    // 仅当本地存在持久化存储时才尝试解析Token
    if (persistRoot) {
      try {
        const userStore = JSON.parse(JSON.parse(persistRoot).user)
        const accessToken = userStore?.currentUser?.accessToken
        if (accessToken) {
          config.headers.token = `Bearer ${accessToken}`
        }
      } catch (err) {
        // 解析失败不阻断请求,后续接口返回401时可全局处理跳登录
        console.error('Token解析异常', err)
      }
    }
    return config
  },
  (error) => Promise.reject(error)
)

2. 修复Login.jsx的跳转逻辑

当前login方法是异步执行的,调用后立刻跳转页面会导致Redux还未完成数据持久化到localStorage,后续页面的鉴权请求无法拿到最新Token,需要等待登录逻辑执行完成后再跳转:

const handleClick = async (e) =>{
  e.preventDefault()
  // 等待登录请求、Redux存储完成后再跳转
  await login(dispatch,{username,password})      
  history.push('/home')
}

3. 简化apicalls.js的登录逻辑

redux-persist会自动将loginSuccess传入的用户数据持久化到localStorage,不需要手动读取Token,删除冗余代码即可:

import { loginFailure, loginStart, loginSuccess } from './userRedux'
import { publicRequest } from '../../requestMethod'

export const login = async (dispatch, user) => {
  dispatch(loginStart())
  try {
    const res = await publicRequest.post('/auth/login', user)
    dispatch(loginSuccess(res.data))
    return res.data
  } catch (error) {
    dispatch(loginFailure())
    return Promise.reject(error)
  }
}

补充优化点

  • 可以给axios新增全局响应拦截器,当接口返回401无权限状态码时,自动清空本地存储并跳转到登录页
  • 路由层面增加守卫逻辑,未登录状态下仅允许访问登录页,避免用户手动输入内部路由地址直接访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:45:08