React中Context跳转后重置问题排查及会话控制方案咨询
问题根源
Navbar里用href跳转属于全页面刷新操作,React Context的状态仅存储在内存中,页面刷新后UserProvider会重新初始化,导致contextUser回到初始值(isEnable为null),触发登录页跳转逻辑。
解决方案
1. 修复Navbar跳转问题
将所有href替换为React Router的Link组件,实现单页无刷新跳转,避免Context状态丢失:
- 先在Navbar中导入
Link:
import { Link } from 'react-router-dom';
- 替换原Button的
href属性,用Link包裹按钮:
{my_pages.map((page) => ( <Link key={page} to={`/${page}`} style={{ textDecoration: 'none' }}> <Button sx={{ my: 2, color: 'whitesmoke', display: 'block', paddingRight: '20px' }}> {page} </Button> </Link> ))}
其他需要跳转的按钮(如Login、SignUp、MASTER)也按此方式修改。
2. 实现Context状态持久化
把用户信息存储到localStorage,确保页面刷新后状态能恢复:
修改context/Context.js:
import React, { createContext, useContext, useState, useEffect } from 'react'; export const UserContext = createContext(); export function UserProvider({ children }) { // 初始化时从localStorage读取状态,无则用默认值 const [contextUser, setContextUser] = useState(() => { const savedUser = localStorage.getItem('userContext'); return savedUser ? JSON.parse(savedUser) : { fullName: "", email: "", token: "", image: null, authorities: [], isEnable: null }; }); const logIn = (userData) => { const newUser = { fullName: userData.user.fullName, email: userData.user.email, token: userData.token, image: null, authorities: userData.user.authorities, isEnable: true }; setContextUser(newUser); localStorage.setItem('userContext', JSON.stringify(newUser)); // 同步到localStorage logContext(); }; const logOut = () => { const loggedOutUser = { fullName: "deleted", email: "", token: "", image: null, authorities: [""], isEnable: false }; setContextUser(loggedOutUser); localStorage.setItem('userContext', JSON.stringify(loggedOutUser)); }; const logContext = () => { console.log(contextUser); }; // 监听localStorage变化,支持多标签页状态同步 useEffect(() => { const handleStorageChange = (e) => { if (e.key === 'userContext') { setContextUser(JSON.parse(e.newValue)); } }; window.addEventListener('storage', handleStorageChange); return () => window.removeEventListener('storage', handleStorageChange); }, []); return ( <UserContext.Provider value={{ contextUser, logIn, logOut, logContext }}> {children} </UserContext.Provider> ); }
3. 优化会话控制(路由守卫)
替换原来的条件渲染路由方式,用Navigate组件实现精细化路由权限控制:
修改App.js:
import { Navigate } from 'react-router-dom'; // 登录权限守卫:未登录则跳转Login const ProtectedRoute = ({ children }) => { const { contextUser } = useContext(UserContext); if (!contextUser.isEnable) { return <Navigate to="/Login" replace />; } return children; }; // 管理员权限守卫:非管理员则跳转首页 const MasterRoute = ({ children }) => { const { contextUser } = useContext(UserContext); if (!contextUser.isEnable || !contextUser.authorities.includes("ROLE_MASTER")) { return <Navigate to="/" replace />; } return children; }; function App() { const theme = createTheme({ palette: { background: { default: '#gray', }, }, }); return ( <> <Navbar/> <Routes> {/* 公开路由 */} <Route path="/" element={<PatientQuery key={10}/>}/> <Route path="/Rapor_Sorgulama" element={<PatientQuery key={1}/>} /> <Route path="/Login" element={<Login key={5}/>}/> <Route path="/SignUp" element={<SignUp key={6}/>}/> <Route path="*" element={<ErrorPage key={7}/>}/> {/* 需要登录的路由 */} <Route path="/Hasta_Listesi" element={ <ProtectedRoute> <PatientList key={11}/> </ProtectedRoute> }/> <Route path="/Rapor_Tanımlama" element={ <ProtectedRoute> <ReportDefine key={12}/> </ProtectedRoute> }/> <Route path="/Tüm_Raporlar" element={ <ProtectedRoute> <AllReports key={13}/> </ProtectedRoute> }/> {/* 管理员专属路由 */} <Route path="/MASTER" element={ <MasterRoute> <Master/> </MasterRoute> } /> </Routes> </> ); } export default App;
内容的提问来源于stack exchange,提问作者lmamBayildi
相关产品推荐
相关产品推荐

