React中useEffect钩子状态异常及JWT令牌刷新丢失问题
问题解决思路
你的核心问题是页面刷新时,useEffect 会在 getUser 异步请求完成前就执行 handleLogout,把 localStorage 里的 token 删掉,导致后续认证失败进入恶性循环。下面是具体的修复方案:
修复步骤
1. 调整导航栏的 useEffect 逻辑
不要在初始渲染时直接判断 User 是否为空就触发登出,应该先检查本地是否存在 token,再等待 getUser 请求完成后处理状态:
// part of navbar.js const { User, getUser } = useContext(NoteContext); const handleLogout = () => { localStorage.removeItem("token"); navigate("/login"); }; useEffect(() => { const token = localStorage.getItem("token"); // 无token直接登出 if (!token) { handleLogout(); return; } // 有token则等待用户信息请求完成后再判断状态 const fetchAndCheckUser = async () => { await getUser(); // 请求完成后若仍无用户信息,说明token无效,执行登出 if (User === "") { handleLogout(); } }; fetchAndCheckUser(); }, [User, getUser, navigate]);
2. 优化Context中的getUser函数
把token有效性判断和清理逻辑整合到函数内部,减少外部重复判断:
// part of context const [User, setUser] = useState(""); const getUser = async () => { const token = localStorage.getItem("token"); // 先检查token是否存在 if (!token) { setUser(""); return; } const response = await fetch(`${host}/api/auth/getuser`, { method: "GET", headers: { "Content-Type": "application/json", "auth-token": token, }, }); if (response.status === 200) { const json = await response.json(); setUser(json.user.email); } else { // token无效时直接清空本地存储和用户状态 localStorage.removeItem("token"); setUser(""); } };
关键逻辑说明
- 优先检查本地token是否存在,避免无意义的请求和误删token
- 用异步函数包裹
getUser,等待请求完成后再判断用户状态,解决异步请求未完成就触发登出的问题 - 给
useEffect补充完整的依赖数组,确保状态更新时逻辑能重新执行
内容的提问来源于stack exchange,提问作者Kartik singh
相关产品推荐
相关产品推荐

