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

使用JWT认证时Token存在但页面刷新后仍被登出的问题

问题分析与解决方案

你的核心问题是页面刷新后Redux状态重置,isAuthenticated回到初始false,且未自动触发token验证逻辑,导致即使localStorage保留token,应用仍判定用户未认证。以下是具体修改步骤:


1. 应用初始化时自动触发token验证

在App.jsx中添加useEffect,页面加载后立即调用loadUser接口验证token有效性,同步Redux状态:

import './App.css'
import Home from './components/UI/Home'
import { Route, Routes } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
import { useEffect } from 'react'
import { loadUser } from './authSlice' // 导入loadUser方法
import Navbar from './components/UI/Navbar'
import Footer from './components/UI/Footer'
import Register from './Pages/Register'
import Login from './Pages/Login'
import Profile from './Pages/Profile'
import Dashboard from './Pages/Dashboard'
import PrivateRoute from './components/Routing/PrivateRoute'

function App() {
  const { isAuthenticated, isLoading } = useSelector(state => state.auth)
  const dispatch = useDispatch()

  // 页面加载时自动验证token
  useEffect(() => {
    dispatch(loadUser())
  }, [dispatch])

  // 加载过程中显示过渡状态,避免页面闪烁
  if (isLoading) {
    return <div>加载中...</div> // 可替换为自定义加载组件
  }

  return (
    <>
    <div className='content-container'>
    <Navbar/>
      <Routes>
        <Route path='/login' element={<Login/>}/>
        <Route path='/profile' element={<PrivateRoute><Profile/></PrivateRoute>}/>
        <Route path='/register' element={<Register/>}/>
        <Route path="/" element={isAuthenticated ? <Dashboard/> : <Home/>} />
      </Routes>
    <Footer/>
    </div>
    </>
  )
}

export default App

2. 优化Redux初始状态与状态更新逻辑

调整初始状态

将isAuthenticated初始值改为null(表示"未确认认证状态"),避免刷新后直接判定为未认证:

// authSlice.js
const initialState = {
  access_token: localStorage.getItem('token'),
  isAuthenticated: null, // 从false改为null
  user: {},
  isLoading: false,
  error: null,
};

修正loadUser的状态处理

移除pending阶段直接设置isAuthenticated的逻辑,等待接口返回后再确认状态:

// authSlice.js extraReducers部分
builder
  .addCase(loadUser.pending, (state) => {
    state.isLoading = true;
    // 移除原有的state.isAuthenticated赋值逻辑
  })
  .addCase(loadUser.rejected, (state, action) => {
    state.isLoading = false;
    state.isAuthenticated = false;
    state.error = action.payload;
    state.access_token = null;
    localStorage.removeItem('token'); // 清除无效token
  })

3. 修复registerUser的赋值错误

registerUser的fulfilled阶段中,localStorage.setItem返回undefined,会导致state.access_token被错误赋值,修正为:

// authSlice.js registerUser fulfilled部分
.addCase(registerUser.fulfilled, (state, action) => {
  localStorage.setItem('token', action.payload.access_token);
  state.access_token = action.payload.access_token; // 先存localStorage,再赋值state
  state.isLoading = false;
  state.isAuthenticated = true;
  state.user = action.payload;
  state.error = null;
})

为什么这样修改?

  1. 自动验证token:页面刷新后主动调用loadUser,让后端验证token有效性,同步Redux的认证状态,避免仅依赖localStorage判断。
  2. 过渡状态优化:初始isAuthenticated设为null,配合isLoading状态,避免刷新后瞬间显示未认证页面,提升用户体验。
  3. 状态一致性:修复registerUser的赋值错误,确保Redux状态与localStorage的token同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:57:49