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

React实现登录功能时react-router-dom路由跳转不符合预期如何解决

React登录路由逻辑修正方案

核心问题梳理

  • App.js未定义/login路由,你写的重定向目标不存在
  • 登录状态判断逻辑完全颠倒:未登录状态反而渲染登录页,登录后才应该跳转到业务页面
  • isLog状态初始值为undefined,首次加载时判断逻辑失效
  • Login组件按钮同时绑定了表单提交事件和独立点击跳转事件,逻辑冲突,且propTypes类型定义错误(isLogIn是父组件传入的函数,不是布尔值)
  • hideMenu判断逻辑错误,登录页不需要展示侧边栏和头部,你写的是仅在根路径显示菜单,和需求相反
  • 所有业务页面(/health、/useradmin)未加登录校验,用户直接输入地址即可绕过登录访问

修正后代码

App.js

import React, { useEffect, useState } from 'react';
import {
  BrowserRouter as Router,
  Redirect,
  Route,
  Switch,
} from 'react-router-dom';

import Header from './components/Header/Header';
import Health from './components/Health/Health';
import Login from './components/Login/Login';
import NotFound from './components/NotFound/NotFound';
import SidebarNav from './components/SidebarNav/SidebarNav';
import UserAdmin from './components/UserAdmin/UserAdmin';

// 封装受保护路由:未登录自动跳转登录页
const ProtectedRoute = ({ component: Component, isLog, ...rest }) => {
  return (
    <Route
      {...rest}
      render={props =>
        isLog ? (
          <Component {...props} />
        ) : (
          <Redirect to="/login" />
        )
      }
    />
  )
}

const App = () => {
  const [hideMenu, setHideMenu] = useState(false);
  // 登录状态默认未登录
  const [isLog, setIsLog] = useState(false);
  useEffect(() => {
    // 只有登录页隐藏菜单,其他页面展示菜单
    setHideMenu(window.location.pathname === '/login');
  }, [window.location.pathname]);

  const handleLogin = (isLog) => {
    setIsLog(isLog);
    // 可选:登录状态可以存到localStorage,刷新页面不用重新登录
    localStorage.setItem('isLog', isLog)
  };

  // 页面刷新时从本地存储恢复登录状态
  useEffect(() => {
    const savedLoginState = localStorage.getItem('isLog') === 'true'
    setIsLog(savedLoginState)
  }, [])

  return (
    <React.Fragment>
      <Router>
        {!hideMenu && (
          <React.Fragment>
            <SidebarNav />
            <Header />
          </React.Fragment>
        )}
        <div className={hideMenu ? '' : 'content'}>
          <main>
            <Switch>
              {/* 登录页路由 */}
              <Route exact path="/login">
                {isLog ? <Redirect to="/health" /> : <Login isLogIn={handleLogin} />}
              </Route>
              {/* 根路径自动跳转:登录了去健康页,没登录去登录页 */}
              <Route exact path="/">
                <Redirect to={isLog ? "/health" : "/login"} />
              </Route>
              {/* 受保护的业务路由,必须登录才能访问 */}
              <ProtectedRoute path="/health" exact component={Health} isLog={isLog} />
              <ProtectedRoute path="/useradmin" exact component={UserAdmin} isLog={isLog} />
              <Route path="*" component={NotFound} />
            </Switch>
          </main>
        </div>
      </Router>
    </React.Fragment>
  );
};

export default App;

Login.jsx

import './Login.css';

import { PropTypes } from 'prop-types';
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
const Login = (props) => {
  let history = useHistory();
  // 给受控组件加初始空值,避免报错
  const [email, setEmail] = useState('');
  const [pwd, setPwd] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    // 这里可以加实际的账号密码校验逻辑
    props.isLogIn(true);
    // 登录状态更新后跳转
    history.push('/health');
  };

  Login.propTypes = {
    // 传入的isLogIn是函数,类型定义修正
    isLogIn: PropTypes.func.isRequired,
  };

  return (
    <div className="div-login">
      <div>
        <form onSubmit={handleSubmit}>
          <input
            type="email"
            value={email}
            placeholder="email..."
            required
            onChange={(e) => setEmail(e.target.value)}
          />
          <input
            type="password"
            value={pwd}
            placeholder="password..."
            required
            onChange={(e) => setPwd(e.target.value)}
          />
          {/* 去掉按钮单独的onClick跳转,走表单提交逻辑 */}
          <button type="submit">
            Log In
          </button>
        </form>
      </div>
    </div>
  );
};

export default Login;

效果说明

  • 用户首次打开站点自动跳转/login登录页,无侧边栏和头部
  • 输入账号密码点击登录后,自动跳转/health页面,展示侧边栏和头部
  • 未登录状态直接输入/health、/useradmin地址,自动跳转回登录页
  • 登录状态刷新页面不需要重新登录(localStorage存储逻辑可根据需要删除)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:09:03