React中如何在多标签页同步用户认证状态?
解决多标签页登录/登出状态不同步问题
问题根源是localStorage的修改仅在当前标签页触发状态更新,其他标签页无法感知变化。我们可以利用浏览器的storage事件监听跨标签页的localStorage变更,从而同步所有标签页的用户状态。
具体修改方案
添加跨标签页状态同步监听:
在useEffect中注册storage事件监听器,当其他标签页修改jwt项时,自动解析新的token并更新用户状态。同时在组件卸载时移除监听器,避免内存泄漏。完善登录/登出逻辑:
当前页面修改localStorage不会触发自身的storage事件,所以登录和登出时需要手动更新当前页面的状态,其他页面则通过storage事件自动同步。修复代码遗留问题:
移除未定义的setIsLoading调用,补充缺失的register方法(基础实现可按需调整)。
修改后的完整代码
import jwt_decode from 'jwt-decode'; import { useEffect, useState } from 'react'; const API = 'http://localhost:5000/api/v1'; const useAuth = () => { const [user, setUser] = useState({}); // 提取通用的用户状态更新逻辑 const updateUserState = () => { const jwt = JSON.parse(localStorage.getItem('jwt')); if (jwt === null) { setUser({}); return; } const decoded = jwt_decode(jwt); setUser({ ...decoded }); }; // 初始化状态 + 监听跨标签页storage变更 useEffect(() => { // 页面加载时初始化用户状态 updateUserState(); // 监听其他标签页的localStorage修改 const handleStorageChange = (e) => { if (e.key === 'jwt') { updateUserState(); } }; window.addEventListener('storage', handleStorageChange); // 组件卸载时移除监听器 return () => { window.removeEventListener('storage', handleStorageChange); }; }, []); const authenticate = (token) => { if (typeof window !== 'undefined') { localStorage.setItem('jwt', JSON.stringify(token)); // 当前页面手动更新状态(自身storage事件不触发) updateUserState(); } }; const login = (user) => { return fetch(`${API}/user/login`, { method: 'post', headers: { 'content-type': 'application/json' }, body: JSON.stringify(user) }); }; // 补充缺失的register基础实现 const register = (user) => { return fetch(`${API}/user/register`, { method: 'post', headers: { 'content-type': 'application/json' }, body: JSON.stringify(user) }); }; const logOut = () => { if (typeof window !== 'undefined') { localStorage.removeItem('jwt'); // 当前页面手动重置用户状态 setUser({}); } }; return { user, register, login, authenticate, logOut, setUser, }; }; export default useAuth;
关键修改说明
updateUserState方法:将重复的状态更新逻辑提取为通用方法,在页面初始化、登录成功、跨标签页storage变更时复用,减少代码冗余。storage事件监听:当其他标签页修改localStorage中的jwt时,自动触发状态同步,确保所有标签页的用户状态一致。- 登录/登出逻辑优化:当前页面修改
localStorage后手动更新状态,避免当前页面状态滞后;其他页面通过storage事件自动同步,无需额外操作。
内容的提问来源于stack exchange,提问作者Shakhawat Hossain SHIHAB
相关产品推荐
相关产品推荐

