React中如何为Admin与Restaurant角色展示不同侧边栏(兼容Router v6)
React 多角色侧边栏导航与路由权限控制(兼容React Router v6)
步骤1:给路由和导航项添加权限配置
先修改路由和导航数据,加入角色权限与角色专属名称的配置:
修改 routes.js
const routes = [ { path: '/', exact: true, name: 'Home' }, { path: '/dashboard', name: 'Dashboard', element: Dashboard, roles: ['Admin', 'Restaurant'] // 两个角色均可访问 }, { path: '/foundation', name: 'Foundation', element: Foundation, roles: ['Admin'] // 仅Admin角色可访问 }, ]
修改 _nav.js
const _nav = [ { component: CNavItem, name: 'Dashboard', nameByRole: { // 不同角色显示不同名称 Restaurant: '我的仪表盘' }, to: '/dashboard', icon: <CIcon icon={cilSpeedometer} customClassName="nav-icon" />, badge: { color: 'info', }, roles: ['Admin', 'Restaurant'] }, { component: CNavItem, name: '基础设置', to: '/foundation', icon: <CIcon icon={cilHome} customClassName="nav-icon" />, badge: { color: 'info', }, roles: ['Admin'] }, ]
步骤2:侧边栏组件过滤导航项
在侧边栏组件(假设为 Sidebar.js)中,根据当前用户角色过滤并渲染导航项:
import { useSelector } from 'react-redux'; import { _nav } from './_nav'; const Sidebar = () => { // 从Redux store获取当前用户角色(需确保登录时已存入store) const currentUser = useSelector(state => state.auth.user); const userRole = currentUser?.role; // 过滤出当前角色有权限的导航项,并替换为角色专属名称 const filteredNav = _nav .filter(item => !item.roles || item.roles.includes(userRole)) .map(item => ({ ...item, name: item.nameByRole?.[userRole] || item.name })); return ( <div className="sidebar"> {filteredNav.map((item, index) => { const Component = item.component; return ( <Component key={index} to={item.to} icon={item.icon} badge={item.badge} > {item.name} </Component> ); })} </div> ); }; export default Sidebar;
步骤3:路由层面的权限控制(防止直接URL访问)
创建 ProtectedRoute 组件,用于保护需要权限的路由:
import { Navigate, Outlet } from 'react-router-dom'; import { useSelector } from 'react-redux'; const ProtectedRoute = ({ allowedRoles }) => { const currentUser = useSelector(state => state.auth.user); const userRole = currentUser?.role; // 未登录跳转登录页 if (!currentUser) { return <Navigate to="/login" replace />; } // 无权限跳转首页 if (allowedRoles && !allowedRoles.includes(userRole)) { return <Navigate to="/" replace />; } return <Outlet />; }; export default ProtectedRoute;
修改 App.js,配置嵌套路由:
import ProtectedRoute from './ProtectedRoute'; import Dashboard from './Dashboard'; import Foundation from './Foundation'; const App = () => { return ( <Provider store={store}> <Suspense fallback={loading}> <Routes> <Route path="*" name="Home" element={<Home />} /> <Route path="/login" name="Login Page" element={<Login />} /> <Route path="/register" name="Register Page" element={<Register />} /> {/* 受保护的路由组 */} <Route element={<ProtectedRoute allowedRoles={['Admin', 'Restaurant']} />}> <Route path="/dashboard" element={<Dashboard />} /> </Route> <Route element={<ProtectedRoute allowedRoles={['Admin']} />}> <Route path="/foundation" element={<Foundation />} /> </Route> </Routes> </Suspense> <ToastContainer></ToastContainer> </Provider> ); }; export default App;
注意事项
- 确保登录时将用户角色(
role)存入Redux store或Context中,以便组件获取 - 若不使用Redux,可改用React Context API管理用户角色状态
- 导航项的
nameByRole可按需自定义,比如给Restaurant角色的Dashboard设置为“我的店铺” - 路由权限控制是必要的,避免用户直接通过URL访问无权限页面
内容的提问来源于stack exchange,提问作者Sabri Yaşar
相关产品推荐
相关产品推荐

