ReactJS多用户角色私有路由无法正常切换问题求助
ReactJS多用户角色私有路由无法正常切换问题求助
嗨,我最近在处理多角色私有路由的问题时卡了好一阵,怎么都搞不定。我的需求是根据用户角色(Client/Admin)来切换对应的私有路由,但现在遇到了问题:当用户角色是client时,能正常显示客户端内容;但角色是admin时,不仅不显示管理员内容,还会被重定向到客户端的路由(因为客户端路由是第一个被添加的)。现在登录后只会显示Client的内容,我希望admin用户登录后能看到管理员页面,client用户看到客户端页面,有没有大佬能帮忙看看呀?
我的代码
App.jsx
function App() { const NewComp = NewHOC(AppRoutes); //CHECK FOR USER LOGGED IN const [user, setUser] = React.useState(null); const handleLogin = () => setUser(clientDetails); const handleLogout = () => setUser(null); return ( <Aux> {user ? ( <button onClick={handleLogout}>Sign Out</button> ) : ( <button onClick={handleLogin}>Sign In</button> )} <Routes> {/* CLIENT ROUTE */} <Route path='/*' element={ <ProtectedRoute redirectPath='/home' isAllowed={!!user && user.permissions.includes('star') && user.roles.includes('client')} > <div>The Client</div> </ProtectedRoute>} /> {/* ADMIN ROUTE */} <Route path='/*' element={ <ProtectedRoute redirectPath='/non-admin' isAllowed={!!user && user.roles.includes('admin')} > <div>The Admin</div> </ProtectedRoute>} /> <Route path={"*"} element={ <Navigate replace to={ "/" }/> }/> </Routes> </Aux> ) }
ProtectedRoute.jsx
const ProtectedRoute = ({ isAllowed, redirectPath = '/', children, }) => { if (!isAllowed) { return <Navigate to={redirectPath} replace />; } return children ? children : <Outlet />; };
用户数据示例
var clientDetails = { id: '1', name: 'Vio', permissions: ['star'], roles: ['client'], }
问题分析(补充的解答视角)
你的问题核心在于React Router的路由匹配规则:<Routes>组件是按从上到下的顺序匹配路由的,一旦找到第一个符合path规则的路由就会停止后续匹配。你现在两个角色路由都用了path='/*',不管用户是什么角色,第一个客户端路由都会被优先命中,后面的管理员路由根本没机会执行,这就是为什么永远只显示客户端内容的原因。
解决方案(补充的解答视角)
这里提供两种可行的修复思路,你可以根据自己的项目需求选择:
方案一:根据角色动态渲染对应路由
只渲染当前用户角色对应的路由,从根源避免匹配冲突:
function App() { const [user, setUser] = React.useState(null); // 可以添加管理员登录的方法用于测试 const handleAdminLogin = () => setUser({ id: '2', name: 'Admin', permissions: ['all'], roles: ['admin'], }); const handleLogout = () => setUser(null); return ( <Aux> {user ? ( <button onClick={handleLogout}>Sign Out</button> ) : ( <> <button onClick={() => setUser(clientDetails)}>登录为Client</button> <button onClick={handleAdminLogin}>登录为Admin</button> </> )} <Routes> {/* 动态渲染对应角色的路由 */} {user?.roles.includes('client') && ( <Route path='/*' element={ <ProtectedRoute redirectPath='/non-client' isAllowed={!!user && user.permissions.includes('star') && user.roles.includes('client')} > <div>The Client</div> </ProtectedRoute> } /> )} {user?.roles.includes('admin') && ( <Route path='/*' element={ <ProtectedRoute redirectPath='/non-admin' isAllowed={!!user && user.roles.includes('admin')} > <div>The Admin</div> </ProtectedRoute> } /> )} {/* 未登录或无匹配角色时重定向 */} <Route path="*" element={<Navigate replace to="/" />} /> </Routes> </Aux> ); }
方案二:合并路由,内部判断角色渲染内容
把两个路由合并成一个,在路由内部根据角色判断要展示的内容,同时调整权限校验逻辑:
function App() { const [user, setUser] = React.useState(null); const handleAdminLogin = () => setUser({ id: '2', name: 'Admin', permissions: ['all'], roles: ['admin'], }); const handleLogout = () => setUser(null); return ( <Aux> {user ? ( <button onClick={handleLogout}>Sign Out</button> ) : ( <> <button onClick={() => setUser(clientDetails)}>登录为Client</button> <button onClick={handleAdminLogin}>登录为Admin</button> </> )} <Routes> <Route path='/*' element={ <ProtectedRoute redirectPath='/' isAllowed={!!user && (user.roles.includes('client') || user.roles.includes('admin'))} > {/* 根据当前角色渲染对应内容 */} {user.roles.includes('client') && <div>The Client</div>} {user.roles.includes('admin') && <div>The Admin</div>} </ProtectedRoute> } /> <Route path="*" element={<Navigate replace to="/" />} /> </Routes> </Aux> ); }
备注:内容来源于stack exchange,提问作者Marian Petrisor
相关产品推荐
相关产品推荐

