React应用的状态默认存储在组件的内存中,当页面刷新时,JavaScript运行环境会重新初始化,内存中的状态数据会被全部清空,这就是刷新后认证状态丢失的根本原因。要解决这个问题,需要把认证状态持久化到不会随页面刷新消失的存储位置,同时做好状态的初始化和同步。

常见解决方案
1. 使用localStorage持久化认证信息
localStorage是浏览器提供的本地存储API,存储的数据不会随页面刷新消失,除非手动清除。我们可以在用户登录成功后将认证Token等信息存入localStorage,应用初始化时再从localStorage中读取状态进行恢复。
登录时存储Token的示例代码如下:
// 登录成功后执行
const handleLoginSuccess = (token) => {
// 将Token存入localStorage
localStorage.setItem('auth_token', token);
// 同时更新React状态
setAuthState({ isLogin: true, token });
};
应用初始化时读取Token恢复状态的示例:
import { useEffect, useState } from 'react';
const useAuthInit = () => {
const [authState, setAuthState] = useState({ isLogin: false, token: null });
useEffect(() => {
// 从localStorage读取存储的Token
const storedToken = localStorage.getItem('auth_token');
if (storedToken) {
// 这里可以添加Token有效性校验逻辑
setAuthState({ isLogin: true, token: storedToken });
}
}, []);
return authState;
};
2. 结合Redux持久化状态
如果项目使用了Redux进行状态管理,可以搭配redux-persist库实现状态的自动持久化,无需手动操作localStorage,减少重复代码。
配置redux-persist的示例:
import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // 默认使用localStorage
import authReducer from './authSlice';
// 持久化配置
const persistConfig = {
key: 'root',
storage,
// 只持久化auth相关的状态
whitelist: ['auth']
};
const persistedReducer = persistReducer(persistConfig, authReducer);
export const store = configureStore({
reducer: persistedReducer,
// 关闭redux-persist的序列化检查
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false
})
});
export const persistor = persistStore(store);
在应用入口处需要包裹PersistGate组件,等待持久化状态恢复后再渲染页面:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './store';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
3. 实现Token自动刷新机制
如果认证Token存在有效期,即使持久化了Token,过期后也会导致认证失效。可以搭配后端提供的刷新Token接口,在Token过期前自动获取新的Token,延长认证状态的有效期。
Token刷新的示例逻辑:
import axios from 'axios';
// 创建axios实例
const request = axios.create({
baseURL: 'https://ipipp.com/api'
});
// 请求拦截器,自动携带Token
request.interceptors.request.use(
(config) => {
const token = localStorage.getItem('auth_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器,处理Token过期
request.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// 如果是401错误且不是刷新Token的请求,尝试刷新Token
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
const refreshToken = localStorage.getItem('refresh_token');
if (refreshToken) {
try {
const res = await axios.post('https://ipipp.com/api/refresh_token', {
refresh_token: refreshToken
});
const newToken = res.data.token;
// 更新存储的Token
localStorage.setItem('auth_token', newToken);
// 重试原请求
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return request(originalRequest);
} catch (refreshError) {
// 刷新Token失败,清除存储的认证信息,跳转到登录页
localStorage.removeItem('auth_token');
localStorage.removeItem('refresh_token');
window.location.href = '/login';
return Promise.reject(refreshError);
}
}
}
return Promise.reject(error);
}
);
export default request;
方案对比与注意事项
不同方案的适用场景和特点如下:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| localStorage手动存储 | 小型项目,无复杂状态管理需求 | 实现简单,无额外依赖 | 需要手动处理读写逻辑,状态分散 |
| Redux+redux-persist | 使用Redux的中大型项目 | 状态管理统一,自动持久化,减少重复代码 | 需要引入额外依赖,配置稍复杂 |
| Token自动刷新 | Token有有效期的所有项目 | 延长认证有效期,提升用户体验 | 需要后端配合提供刷新接口,逻辑稍复杂 |
需要注意,localStorage存储的数据可以被客户端脚本读取,不建议存储敏感信息如用户密码等,同时要做好Token的有效期校验和异常处理,避免认证状态异常导致的安全问题。
React认证状态管理localStorageReduxToken刷新修改时间:2026-07-10 19:51:38