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

ReactJS:未授权用户访问私有路由时打开登录模态框(非Redux方案)

实现私有路由时弹出登录模态框(无需Redux)

嘿,我完全懂你想要的效果——把原来的重定向登录改成弹出模态框,还不想用Redux来折腾状态管理,这事儿其实很简单,咱们直接在PrivateRoute组件内部搞定就行,不用复杂的全局状态方案。

核心思路

咱们不再做页面重定向,而是在用户访问私有路由且未认证时:

  1. 记录用户原本想要访问的路径
  2. 弹出登录模态框
  3. 登录成功后直接跳转到记录的路径

修改后的PrivateRoute代码

先上完整代码,我会一步步解释:

import React, { useState, useEffect } from 'react';
import { Route, useLocation, useHistory } from 'react-router-dom';

// 自定义登录模态框组件
const LoginModal = ({ isOpen, onClose, redirectPath }) => {
  const history = useHistory();

  // 登录成功后的处理逻辑
  const handleLoginSuccess = () => {
    // 跳转到用户原本想访问的页面
    history.push(redirectPath);
    // 关闭模态框
    onClose();
  };

  // 模态框未打开时不渲染任何内容
  if (!isOpen) return null;

  return (
    {/* 模态框遮罩层 */}
    <div style={{
      position: 'fixed',
      top: 0,
      left: 0,
      width: '100%',
      height: '100%',
      backgroundColor: 'rgba(0, 0, 0, 0.5)',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center'
    }}>
      {/* 模态框内容 */}
      <div style={{
        backgroundColor: 'white',
        padding: '2rem',
        borderRadius: '8px',
        width: '90%',
        maxWidth: '400px'
      }}>
        <h3>请登录</h3>
        {/* 这里替换成你的实际登录表单 */}
        <div style={{ margin: '1rem 0' }}>
          <label style={{ display: 'block', marginBottom: '0.5rem' }}>用户名</label>
          <input type="text" style={{ width: '100%', padding: '0.5rem' }} />
        </div>
        <div style={{ margin: '1rem 0' }}>
          <label style={{ display: 'block', marginBottom: '0.5rem' }}>密码</label>
          <input type="password" style={{ width: '100%', padding: '0.5rem' }} />
        </div>
        <div style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
          <button onClick={onClose} style={{ padding: '0.5rem 1rem' }}>取消</button>
          <button onClick={handleLoginSuccess} style={{ padding: '0.5rem 1rem', backgroundColor: '#007bff', color: 'white', border: 'none', borderRadius: '4px' }}>登录</button>
        </div>
      </div>
    </div>
  );
};

// 修改后的私有路由组件
const PrivateRoute = ({ component: Component, isAuthenticated, ...rest }) => {
  const [showLoginModal, setShowLoginModal] = useState(false);
  const [redirectPath, setRedirectPath] = useState('');
  const location = useLocation();

  useEffect(() => {
    // 监听认证状态和路由变化:如果未认证,记录路径并打开模态框
    if (!isAuthenticated) {
      // 记录完整的路径(包含查询参数)
      setRedirectPath(location.pathname + location.search);
      setShowLoginModal(true);
    } else {
      // 已认证时关闭模态框
      setShowLoginModal(false);
    }
  }, [isAuthenticated, location]);

  return (
    <>
      <Route
        {...rest}
        render={(props) => {
          // 已认证则渲染目标组件,未认证则不渲染任何内容(只显示模态框)
          return isAuthenticated ? <Component {...props} /> : null;
        }}
      />
      {/* 挂载登录模态框 */}
      <LoginModal
        isOpen={showLoginModal}
        onClose={() => setShowLoginModal(false)}
        redirectPath={redirectPath}
      />
    </>
  );
};

export default PrivateRoute;

路由配置用法

和你原来的用法几乎一样,只需要传入isAuthenticated的状态(比如从localStorage或者Context获取):

import { BrowserRouter as Router, Switch } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import Dashboard from './Dashboard';
import SignInPage from './SignInPage';

const App = () => {
  // 这里示例从localStorage获取认证状态,你可以替换成自己的逻辑
  const isAuthenticated = !!localStorage.getItem('authToken');

  return (
    <Router>
      <Switch>
        <Route path="/sign-in" component={SignInPage} />
        <PrivateRoute
          path="/dashboard"
          component={Dashboard}
          isAuthenticated={isAuthenticated}
        />
        {/* 其他私有路由同理 */}
      </Switch>
    </Router>
  );
};

export default App;

注意事项

  1. React Router版本适配:如果你用的是v6,需要把Route的component换成element,useHistory换成useNavigate,核心逻辑不变。
  2. 认证状态管理:你可以用React Context、localStorage或者其他轻量方案来管理isAuthenticated,不用Redux也完全没问题。
  3. 关闭模态框的处理:如果用户点击取消,你可以在onClose里加一句history.push('/')跳转到首页,根据需求调整即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:04:24