React嵌套路由路径渲染异常及Admin权限控制问题求助
React嵌套路由与权限控制问题
问题描述
- 点击侧边栏菜单时,路由地址能跳转到
/{指定路由路径},但无法正确渲染对应页面组件 - 需实现权限控制,仅允许admin角色访问特定标签页
相关代码
index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import { Provider } from 'react-redux'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; import { AuthProvider } from './context/AuthProvider'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter> <AuthProvider> <Routes> <Route path="/*" element={ <App /> } /> </Routes> </AuthProvider> </BrowserRouter> </React.StrictMode> );
App.js
import React from "react"; import { Route, Routes } from "react-router-dom"; import Layout from "./Components/PublicPages/Layout"; import RequireAuth from "./Components/RequireAuth"; import Unauthorized from "./Components/PublicPages/Unauthorized"; import Missing from "./Components/PublicPages/Missing"; import Register from "./Components/PublicPages/Register"; import Login from "./Components/PublicPages/Login"; import Admin from "./Components/RolePages/Admin"; import AdminHome from "./Components/RolePages/AdminLayoutComponents/AdminHome"; import Complaints from "./Components/RolePages/AdminLayoutComponents/Complaints"; function App() { return ( <React.Suspense fallback={<div>Loading</div>}> <Routes> <Route path="/register" element={<Register />} /> {/* public routes */} <Route path="/login" element={<Login />} /> <Route path="/unauthorized" element={<Unauthorized />} /> <Route path="/" element={<Layout />}> {/* we want to protect these routes */} <Route element={<RequireAuth allowedPermissions="admin" />}> <Route index={true} element={<Admin />} /> <Route path="/admin" element={<AdminHome />} /> <Route path='/complaints' element={<Complaints />} /> </Route> {/* catch all */} </Route> <Route path="*" element={<Missing />} /> </Routes> </React.Suspense> ); } export default App;
Admin.jsx
import * as React from "react"; import PropTypes from "prop-types"; import AppBar from "@mui/material/AppBar"; import Box from "@mui/material/Box"; import CssBaseline from "@mui/material/CssBaseline"; import Divider from "@mui/material/Divider"; import Drawer from "@mui/material/Drawer"; import IconButton from "@mui/material/IconButton"; import InboxIcon from "@mui/icons-material/MoveToInbox"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; import MailIcon from "@mui/icons-material/Mail"; import MenuIcon from "@mui/icons-material/Menu"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; import { NavLink } from "react-router-dom"; const drawerWidth = 240; function Admin(props) { const { window } = props; const [mobileOpen, setMobileOpen] = React.useState(false); const [isClosing, setIsClosing] = React.useState(false); const handleDrawerClose = () => { setIsClosing(true); setMobileOpen(false); }; const handleDrawerTransitionEnd = () => { setIsClosing(false); }; const handleDrawerToggle = () => { if (!isClosing) { setMobileOpen(!mobileOpen); } }; const sidebarItems = [ { title: "Admin Home", link: "/admin" }, { title: "Complaints", link: "/complaints" }, { title: "Account Opener Home", link: "/account-opener-home" }, { title: "Bank Home", link: "/bank-home" }, { title: "Higher Management Home", link: "/higher-management-home" }, { title: "Manage Users", link: "/manage-users" }, { title: "Logout", link: "/logout" }, ]; const drawer = ( <div style={{ color: "#b8c7ce" }}> <Divider /> <List> {sidebarItems.map((text, index) => ( <ListItem disablePadding key={text}> <NavLink to={`/${text.link}`} style={{ textDecoration: "none", color: "inherit" }} > <ListItemButton> <ListItemText primary={text.title} /> </ListItemButton> </NavLink> </ListItem> ))} </List> <Divider /> </div> ); return ( <Box sx={{ display: "flex" }}> <CssBaseline /> <AppBar position="fixed" sx={{ width: { sm: `calc(100% - ${drawerWidth}px)` }, ml: { sm: `${drawerWidth}px` }, }} > <Toolbar> <IconButton color="inherit" aria-label="open drawer" edge="start" onClick={handleDrawerToggle} sx={{ mr: 2, display: { sm: "none" } }} > <MenuIcon /> </IconButton> </Toolbar> </AppBar> <Box component="nav" sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }} aria-label="mailbox folders" > <Drawer variant="temporary" open={mobileOpen} onTransitionEnd={handleDrawerTransitionEnd} onClose={handleDrawerClose} ModalProps={{ keepMounted: true, // Better open performance on mobile. }} sx={{ display: { xs: "block", sm: "none" }, "& .MuiDrawer-paper": { boxSizing: "border-box", width: drawerWidth, }, }} > <img src={jazzcashLogo} alt="Jazzcash Logo" /> {drawer} </Drawer> <Drawer variant="permanent" sx={{ display: { xs: "none", sm: "block" }, border: "2px solid black", "& .MuiDrawer-paper": { boxSizing: "border-box", backgroundColor: "rgb(54,55,64)", width: drawerWidth, }, }} open > {drawer} </Drawer> </Box> </Box> ); } export default Admin;
useAuth.js
import { useContext } from "react"; import AuthContext from "../context/AuthProvider"; const useAuth = () => { return useContext(AuthContext); } export default useAuth;
AuthProvider.js
import { createContext, useState } from "react"; const AuthContext = createContext({}); export const AuthProvider = ({ children }) => { const [auth, setAuth] = useState({}); return ( <AuthContext.Provider value={{ auth, setAuth }}> {children} </AuthContext.Provider> ) } export default AuthContext;
已尝试的解决方案
- 排查过React Router v6嵌套路由渲染问题的相关方案
- 将侧边栏的
NavLink替换为Link,问题仍未解决
内容的提问来源于stack exchange,提问作者Sajeel Zafar
相关产品推荐
相关产品推荐

