You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 01:32:02