如何用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
相关产品推荐
相关产品推荐

