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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 09:45:30