React状态钩子不响应:登出后logged变量未更新导致无法跳转
问题分析与解决方案
你遇到的核心问题是:logged 状态只在组件首次挂载时从 localStorage 获取值,之后当你在 handleCloseSession 中移除 token 时,logged 并不会自动更新——因为 React 的 useState 不会主动监听 localStorage 的变化。这就导致 useEffect 里的跳转逻辑根本触发不了。
下面是具体的修复步骤:
1. 手动同步状态与 localStorage
在执行移除 token 的操作后,直接调用 setLogged(false) 更新状态,这样就能让 React 感知到状态变化,进而触发后续的跳转逻辑。
2. 修复 useEffect 的无限循环问题
你的 useEffect 没有设置依赖数组,这会导致它在每次组件渲染时都执行,很容易引发性能问题。我们需要把 logged 加入依赖数组,让它只在 logged 状态变化时执行。
3. 可选:监听全局 storage 事件(跨标签页同步)
如果需要支持其他标签页修改 localStorage 时当前页面也能同步状态,可以添加一个监听 storage 事件的 useEffect,确保状态始终和 localStorage 保持一致。
修复后的完整代码
import React, { useState, useEffect } from "react" import { useHistory } from "react-router-dom" import man from "../../assets/img/people/man.jpg" const ProfileMenu = () => { const history = useHistory() const [logged, setLogged] = useState(localStorage.getItem('token') ? true : false) const [isOpen, setOpen] = useState(false) useEffect(() => { // 仅在 logged 变为 false 时执行跳转 if (!logged) { handleRedirection() } }, [logged, history]) // 添加依赖数组,避免无限循环 // 可选:监听 storage 事件,跨标签页同步状态 useEffect(() => { const handleStorageChange = () => { const hasToken = !!localStorage.getItem('token') setLogged(hasToken) } window.addEventListener('storage', handleStorageChange) return () => window.removeEventListener('storage', handleStorageChange) }, []) const handleRedirection = () => { history.push('/login') } const handleMenu = () => { setOpen(!isOpen) } const handleCloseSession = () => { localStorage.removeItem('token') // 手动更新 logged 状态 setLogged(false) } return ( <div className="dropdown"> <button className="profile-menu-button" style={{ backgroundImage: `url('${man}')` }} onClick={handleMenu}> </button> <div className="dropdown-content" style={{ display: isOpen ? 'block' : 'none' }}> <ul className="list"> <li> <a>Perfil</a> </li> <hr/> <li> <a>Editar perfil</a> </li> <li> <a>Editar red</a> </li> <hr/> <li> <a>Configuración de cuenta</a> </li> <li> <a onClick={handleCloseSession}>Cerrar sesión</a> </li> </ul> </div> </div> ) } export default ProfileMenu
为什么这样能解决问题?
- 手动调用
setLogged(false)直接更新了组件状态,让 React 重新渲染并触发useEffect里的跳转逻辑。 - 给
useEffect添加依赖数组后,它只会在logged或history变化时执行,避免了不必要的重复渲染。 - 新增的
storage事件监听,能确保当其他标签页修改localStorage时,当前页面的状态也能同步更新,提升了多标签页场景下的用户体验。
内容的提问来源于stack exchange,提问作者user12207614
相关产品推荐
相关产品推荐

