ReactJS中刷新页面时如何利用localStorage的JWT更新登录状态
解决React页面刷新时用localStorage的JWT恢复登录状态的方案
我来帮你搞定这个页面刷新后登录状态丢失的问题——这在React单页应用里是个非常常见的场景。核心思路就是在应用初始化阶段,自动从localStorage读取JWT并验证有效性,然后同步更新你的登录状态state。下面是具体的实现步骤,结合你的场景来拆解:
1. 先写一个JWT验证工具函数
首先我们需要一个函数来检查localStorage里的token是否存在、是否未过期。毕竟存了token不代表它还能用,过期的token是无效的:
const isTokenValid = () => { // 从localStorage获取token const token = localStorage.getItem('jwtToken'); if (!token) return false; try { // 解析JWT的payload部分(注意:这里只是前端校验,后端还是会再验证的) const decodedPayload = JSON.parse(atob(token.split('.')[1])); // 把当前时间转成秒,和token的过期时间对比 const currentTimestamp = Date.now() / 1000; return decodedPayload.exp > currentTimestamp; } catch (err) { // 解析失败说明token格式有问题,直接返回无效 return false; } };
2. 在根组件初始化时检查并更新登录状态
把检查逻辑放在你的根组件(比如App.js)的useEffect里,因为页面刷新后根组件会重新挂载,这个useEffect会自动执行一次:
假设你的登录状态是用useState管理的,比如:
const [isLoggedIn, setIsLoggedIn] = useState(false); const [currentUser, setCurrentUser] = useState(null);
然后添加这个useEffect:
useEffect(() => { const syncAuthState = () => { const tokenIsValid = isTokenValid(); if (tokenIsValid) { // token有效,更新登录状态 setIsLoggedIn(true); // 顺便把用户信息解析出来存入state(可选,根据你的token结构调整) const token = localStorage.getItem('jwtToken'); const decodedPayload = JSON.parse(atob(token.split('.')[1])); setCurrentUser(decodedPayload.user); } else { // token无效或者不存在,清空localStorage并保持未登录状态 localStorage.removeItem('jwtToken'); setIsLoggedIn(false); setCurrentUser(null); } }; syncAuthState(); }, []); // 空依赖数组确保只在组件挂载时执行一次
3. 同步登录/登出操作的状态与localStorage
要保证登录和登出时,state和localStorage是同步的,避免出现不一致的情况:
- 登录成功时:
const handleLogin = async (loginFormData) => { try { const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(loginFormData) }); const { token } = await response.json(); // 把token存入localStorage localStorage.setItem('jwtToken', token); // 更新登录状态和用户信息 setIsLoggedIn(true); const decodedPayload = JSON.parse(atob(token.split('.')[1])); setCurrentUser(decodedPayload.user); } catch (err) { console.error('登录失败:', err); } };
- 登出时:
const handleLogout = () => { // 清空localStorage里的token localStorage.removeItem('jwtToken'); // 重置登录状态 setIsLoggedIn(false); setCurrentUser(null); // 如果用了react-router,跳转到登录页 // navigate('/login'); };
4. 优化:给请求加拦截器处理token失效
如果你的项目用了axios这类请求库,可以加个响应拦截器,当后端返回401(未授权)时,自动清空状态并跳转到登录页,避免用户停在无效状态:
import axios from 'axios'; // 请求拦截器:自动给请求带上token axios.interceptors.request.use( (config) => { const token = localStorage.getItem('jwtToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); // 响应拦截器:处理401状态 axios.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { localStorage.removeItem('jwtToken'); setIsLoggedIn(false); setCurrentUser(null); // 跳转到登录页 navigate('/login'); } return Promise.reject(error); } );
这样一来,页面刷新后,应用会自动检查localStorage里的JWT是否有效,有效就把登录状态更新回state,用户就不会看到“未登录”的状态了,同时请求也能正常带上token完成授权。
内容的提问来源于stack exchange,提问作者Maruth51
相关产品推荐
相关产品推荐

