React路由跳转时Navbar组件admin状态被重置如何解决
问题根因
- 你当前的
Navbar组件大概率是在每个页面(Team、Members等)内部单独引入渲染,路由切换时页面组件会卸载重建,连带Navbar也会重新挂载,内部的admin、passedData等局部状态自然会被重置。 useEffect的依赖数组仅设置了user,当dataprops、路由参数发生变化时,不会重新触发admin权限校验逻辑,就算数据正确传递也不会更新admin状态。- 跳转
Medlemar路由时你把passedData存在了路由state中,但现有Navbar没有从路由state取值的逻辑,跳转后passedData为空,自然不会触发admin查询。
解决方案
步骤1:调整路由结构,避免Navbar重复挂载
把Navbar移到Router内部、Switch外层,所有路由共享同一个Navbar实例,路由切换时不会被卸载,状态自然保留:
function App() { return ( <> <Router> {/* Navbar放在这里,全局唯一实例 */} <Navbar /> <Switch> <Route path="/" exact component={Home} /> <Route path="/logg-inn" component={Login} /> <Route path="/lag/:id" exact component={Team} /> <Route path="/profil" component={Profile} /> <Route path="/registrer-deg" component={Signup} /> <Route path="/lag" exact component={Teams} /> <Route path="/lag/:id/innstillingar" exact component={TeamSettings} /> <Route path="/lag/:id/betaling" exact component={Payment} /> <Route path="/lag/:id/arrangement" exact component={Events} /> <Route path="/lag/:id/admin/medlemar" component={Members} /> </Switch> </Router> </> ); }
步骤2:修正Navbar逻辑,补全触发条件
调整Navbar的依赖和取值逻辑,支持从路由state取数据,数据变化时自动重新校验admin权限:
import { useLocation } from 'react-router-dom' function Navbar({ data }) { const [user, setUser] = useState(null) const [admin, setAdmin] = useState(false) const location = useLocation() // 用户登录状态监听单独抽离,只执行一次,避免重复监听 useEffect(() => { const unsubscribe = firebase.auth().onAuthStateChanged((user) => { setUser(user) }) // 组件卸载时取消监听,避免内存泄漏 return () => unsubscribe() }, []) // admin权限校验逻辑,依赖变化时自动重新执行 useEffect(() => { // 优先取路由state的传递数据,没有就取props传入的data const currentData = location.state?.passedData || data // 没有登录或者没有团队ID时直接置为非管理员 if (!user || !currentData?.teamID) { setAdmin(false) return } // 查询管理员权限 firebase.firestore().collection('teams').doc(currentData.teamID).collection('members').doc(user.uid).get().then((snapshot) => { const administrator = snapshot.get('role') setAdmin(administrator === 'admin') }) }, [user, data, location.state]) // 原有return的JSX逻辑保持不变即可 return ( <nav className='navbar'> <ul className='nav-menu-items'> <li className="nav-text"> <Link to="/"> <AiIcons.AiFillDashboard size="1.4em" className="icon" /> <span>Dashboard</span> </Link> </li> <li className="nav-text"> <Link to="/lag"> <AiIcons.AiOutlineTeam size="1.4em" className="icon" /> <span>Lag</span> </Link> </li> <li className="nav-text"> <Link to="/profil"> <BsIcons.BsPerson size="1.4em" className="icon" /> <span>Profil</span> </Link> </li> <li className="nav-text"> <Link to="/betaling"> <GiIcons.GiPayMoney size="1.4em" className="icon" /> <span>Betaling</span> </Link> </li> </ul> {admin ? <> <span className="admin-text">Admin</span> <div className="navbar-divider"></div> <ul className="nav-menu-items"> <li className="nav-text"> <Link to={{ pathname: `/lag/${data.teamID}/admin/medlemar`, state: { passedData: data, } }}> <BsIcons.BsPeopleFill className="icon" size="1.4em" /> <span>Medlemar</span> </Link> </li> </ul> </> : null } </nav> ) }
可选长效优化
如果应用规模较大,建议用React Context、Zustand这类状态管理工具把用户信息、admin权限全局存储,所有组件可以直接消费,不会因为组件挂载卸载丢失状态,也不用重复查询权限。
内容的提问来源于stack exchange,提问作者Daniel Olsen
相关产品推荐
相关产品推荐

