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

如何用React实现对接API的登录页面与带动态侧边栏的仪表盘

React 对接API实现登录页与动态侧边栏仪表盘

一、实现登录页面

登录页面需完成表单输入、API验证、登录成功后存储凭证并跳转的核心逻辑。

1. 依赖准备

先安装react-router-dom用于页面路由跳转:

npm install react-router-dom

2. 登录组件代码

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';

const Login = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const navigate = useNavigate();

  const handleLogin = async (e) => {
    e.preventDefault();
    setError('');

    try {
      const response = await fetch('http://localhost:9292/api/login', { // 替换为你的登录API地址
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ username, password }),
      });

      if (response.ok) {
        const data = await response.json();
        // 存储登录凭证到localStorage
        localStorage.setItem('authToken', data.token);
        // 跳转到仪表盘
        navigate('/dashboard');
      } else {
        const errorData = await response.json();
        setError(errorData.message || '登录失败,请检查账号密码');
      }
    } catch (err) {
      setError('网络错误,请稍后重试');
      console.error('登录请求失败:', err);
    }
  };

  return (
    <div style={{ maxWidth: '300px', margin: '50px auto' }}>
      <h2>登录</h2>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <form onSubmit={handleLogin}>
        <div>
          <label>用户名:</label>
          <input
            type="text"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
            required
            style={{ width: '100%', margin: '5px 0 15px' }}
          />
        </div>
        <div>
          <label>密码:</label>
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
            style={{ width: '100%', margin: '5px 0 15px' }}
          />
        </div>
        <button type="submit" style={{ width: '100%', padding: '8px' }}>登录</button>
      </form>
    </div>
  );
};

export default Login;

二、完善动态侧边栏组件

基于你提供的代码,补充身份验证头和路由跳转功能:

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';

const Sidebar = () => {
  const [menuData, setMenuData] = useState([]);

  const fetchMenuData = async () => {
    try {
      const authToken = localStorage.getItem('authToken');
      if (!authToken) {
        console.error('未检测到登录凭证');
        return;
      }

      const response = await fetch('http://localhost:9292/fndMenu/menuloadbyuser', {
        method: "GET",
        headers: {
          'Authorization': `Bearer ${authToken}`, // 携带登录token
          'Content-Type': 'application/json'
        },
      });

      if (response.ok) {
        const data = await response.json();
        setMenuData(Array.isArray(data) ? data : [data]);
      } else {
        console.error("获取菜单数据失败,状态码:", response.status);
        // token失效时跳回登录页
        if (response.status === 401) {
          localStorage.removeItem('authToken');
          window.location.href = '/login';
        }
      }
    } catch (error) {
      console.error('获取菜单数据出错:', error);
    }
  };

  useEffect(() => {
    fetchMenuData();
  }, []);

  const renderSubMenus = (subMenus) => {
    if (!subMenus || subMenus.length === 0) {
      return null;
    }
    return (
      <ul style={{ marginLeft: '20px', listStyle: 'none' }}>
        {subMenus.map((submenu) => (
          <li key={submenu.menuItemId}>
            <Link to={submenu.menuUrl || '#'} style={{ textDecoration: 'none', color: '#333' }}>
              {submenu.menuItemDesc}
            </Link>
            {renderSubMenus(submenu.subMenus)}
          </li>
        ))}
      </ul>
    );
  };

  return (
    <div style={{ width: '250px', backgroundColor: '#f5f5f5', padding: '20px', minHeight: '100vh' }}>
      <h2>侧边菜单</h2>
      <ul style={{ listStyle: 'none', padding: 0 }}>
        {menuData.map((menuItem) => (
          <li key={menuItem.menuItemId} style={{ marginBottom: '10px' }}>
            <Link to={menuItem.menuUrl || '#'} style={{ textDecoration: 'none', color: '#333', fontSize: '16px' }}>
              {menuItem.menuItemDesc}
            </Link>
            {renderSubMenus(menuItem.subMenus)}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Sidebar;

三、仪表盘组件与路由配置

1. 仪表盘组件

import React from 'react';
import Sidebar from './Sidebar';

const Dashboard = () => {
  return (
    <div style={{ display: 'flex' }}>
      <Sidebar />
      <div style={{ flex: 1, padding: '20px' }}>
        <h1>仪表盘</h1>
        <p>欢迎登录,这里是你的主页面</p>
      </div>
    </div>
  );
};

export default Dashboard;

2. 路由配置(App.js)

import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import Login from './Login';
import Dashboard from './Dashboard';

// 路由守卫:拦截未登录用户访问仪表盘
const ProtectedRoute = ({ children }) => {
  const isAuthenticated = localStorage.getItem('authToken') !== null;
  return isAuthenticated ? children : <Navigate to="/login" />;
};

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/dashboard" element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        } />
        <Route path="/" element={<Navigate to="/login" />} />
      </Routes>
    </Router>
  );
}

export default App;

核心说明

  • 凭证管理:登录成功后将token存入localStorage,后续API请求携带该token完成身份验证
  • 路由保护:通过ProtectedRoute确保未登录用户无法直接访问仪表盘
  • 动态菜单:递归渲染多级菜单,使用Link组件实现页面跳转
  • 错误处理:API请求失败时打印日志,token失效时自动跳转回登录页

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:47:17