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

如何基于localStorage判断登录状态实现React Router路由重定向?

原代码问题点

  • 用普通变量userLogged存储登录状态,useEffect内修改变量不会触发组件重渲染,路由无法响应状态变化
  • 依赖storage事件同步状态逻辑错误:该事件仅在非当前标签页修改localStorage时触发,当前页面执行setItem不会触发该事件,同页面登录/登出时状态完全不会更新
  • 条件渲染路由逻辑错误:未登录状态下根本没有注册/dashboard路由,手动输入地址会直接匹配失败,无法实现自动跳转
  • 未做类型转换:localStorage仅支持存储字符串,你存入的布尔值true/false会被转成"true"/"false",直接判断会出现"false"被识别为真值的bug
  • React.StrictMode位置错误,该组件应该放在入口文件包裹根组件,不能写在App的渲染逻辑内

修正方案

核心思路是放弃条件渲染路由,通过路由守卫做访问控制,用状态管理登录态触发重渲染,同页面登录/登出操作完成后主动执行路由跳转,storage事件仅用来做多标签页状态同步。

第一步:修改App.js代码

import { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import Home from './pages/Home';
import Dashboard from './pages/Dashboard';

// 受保护路由守卫:未登录访问时重定向到/home
function RequireAuth({ children }) {
  const location = useLocation();
  const isLogged = localStorage.getItem("userLogged") === "true";
  if (!isLogged) {
    return <Navigate to="/home" replace state={{ from: location }} />;
  }
  return children;
}

// 公开路由守卫:已登录访问时重定向到/dashboard
function RedirectIfLogged({ children }) {
  const isLogged = localStorage.getItem("userLogged") === "true";
  if (isLogged) {
    return <Navigate to="/dashboard" replace />;
  }
  return children;
}

function App() {
  // 初始化时直接读取localStorage值,统一转成布尔值
  const [userLogged, setUserLogged] = useState(() => {
    return localStorage.getItem("userLogged") === "true";
  });

  useEffect(() => {
    const syncLoginStatus = () => {
      setUserLogged(localStorage.getItem("userLogged") === "true");
    };
    // 仅用来同步多标签页的登录状态变化
    window.addEventListener("storage", syncLoginStatus);
    return () => window.removeEventListener("storage", syncLoginStatus);
  }, []);

  return (
    <div className="App">
      <Router>
        <Routes>
          {/* 根路径自动适配登录状态跳转 */}
          <Route 
            path="/" 
            element={userLogged ? <Navigate to="/dashboard" replace /> : <Navigate to="/home" replace />} 
          />
          {/* home页:已登录不可访问 */}
          <Route 
            path="/home" 
            element={
              <RedirectIfLogged>
                <Home />
              </RedirectIfLogged>
            } 
          />
          {/* dashboard页:未登录不可访问 */}
          <Route 
            path="/dashboard" 
            element={
              <RequireAuth>
                <Dashboard />
              </RequireAuth>
            } 
          />
          {/* 404兜底 */}
          <Route 
            path="*" 
            element={userLogged ? <Navigate to="/dashboard" replace /> : <Navigate to="/home" replace />} 
          />
        </Routes>
      </Router>
    </div>
  );
}

export default App;

第二步:调整入口文件index.js

把React.StrictMode移到入口文件,不要写在App内部:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

第三步:补全页面内的登录/登出跳转逻辑

因为同页面修改localStorage不会触发storage事件,登录/登出操作完成后要主动执行跳转:

  • Home页面登录逻辑示例:
import { useNavigate } from 'react-router-dom';

function Home() {
  const navigate = useNavigate();
  const handleLogin = () => {
    // 省略你的登录校验逻辑,登录成功后执行
    localStorage.setItem("userLogged", "true"); // 注意存字符串格式的"true"
    navigate("/dashboard", { replace: true });
  };

  return (
    // 你的页面代码
    <button onClick={handleLogin}>登录</button>
  )
}
export default Home;
  • Dashboard页面登出逻辑示例:
import { useNavigate } from 'react-router-dom';

function Dashboard() {
  const navigate = useNavigate();
  const handleLogout = () => {
    localStorage.setItem("userLogged", "false");
    // 也可以直接用localStorage.removeItem("userLogged")清除标识
    navigate("/home", { replace: true });
  };

  return (
    // 你的页面代码
    <button onClick={handleLogout}>退出登录</button>
  )
}
export default Dashboard;

实现效果

  • 登录成功后自动跳转到/dashboard,手动输入/home地址也会被自动拦回dashboard
  • 登出后自动跳回/home,手动输入/dashboard地址会被自动拦回home
  • 多标签页下登录/登出状态会自动同步,A标签页登出后B标签页会自动跳转对应页面

内容的提问来源于stack exchange,提问作者user18150656

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:57:19