条件路由在 React Router 中不起作用

Conditional routes not working in React Router

我只想在用户具有访问它们的适当角色时允许路由。我在前端和后端都进行了检查,但是在使用 Switch 时有些东西不起作用。

 {localStorage.getItem("roles") && localStorage.getItem("roles").split(",").includes("CONTRIBUTOR") &&
              <>
                {/* Contributor Routes */}
                <Route exact path="/contributor/upload" component={ContributorUploadPage}/>
                <Route exact path="/contributor/edit/:rawContentId" component={ContributorEditPage}/>
                <Route exact path="/contributor" component={ContributorListPage}/>
               </> }

              {localStorage.getItem("roles") && localStorage.getItem("roles").split(",").includes("EDITOR") &&
                //{/* Editor Routes */}
                <>
                <Route exact path="/editor/search" component={EditorSearch}/>
                <Route path="/editor/upload" component={EditorUploadPage}/>
                <Route exact path="/editor/edit/:finalContentId" component={EditorEditPage}/>
                <Route exact path="/editor" component={EditorListPage}/>
                </>
              }

              {localStorage.getItem("roles") && localStorage.getItem("roles").split(",").map(item => (item === "SUB_PERVIEW" || item === "SUB_SUBSCRIPTION" 
              || item === "SUB_FREE" ? true : false)) &&
              <>
                {/* Subscriber Routes */}
                <Route exact path="/content" component={ContentPage}/>
              </> }

<Route path="/404" component={NotFoundPage}/>
              <Redirect to="/404"/>

如果我现在转到 /editor,即使我没有合适的角色,我也不会被重定向到 /404。如果我删除所有条件,则会呈现 /404 页面。

只有 RouteRedirectSwitch 组件的有效子项,React 片段正在 returned 并扰乱了路由匹配。

您可以在要有条件地渲染的每个“组”或子路线区域周围放置一个 Route。 “技巧”是return将分组的子路由在另一个开关内进行匹配。

我还建议将角色的获取分解为实用函数,以使您的代码更DRY

const getRoles = () => (localStorage.getItem("roles") || '').split(",");

...

<Switch>
  {/* Contributor Routes */}
  {getRoles().includes("CONTRIBUTOR") && (
    <Route path="/contributor">
      <Switch>
        <Route path="/contributor/upload" component={ContributorUploadPage}/>
        <Route path="/contributor/edit/:rawContentId" component={ContributorEditPage}/>
        <Route path="/contributor" component={ContributorListPage}/>
      </Switch>
    </Route>
  )}

  {/* Editor Routes */}
  {getRoles().includes("EDITOR") && (
    <Route path="/editor">
      <Switch>
        <Route path="/editor/search" component={EditorSearch}/>
        <Route path="/editor/upload" component={EditorUploadPage}/>
        <Route path="/editor/edit/:finalContentId" component={EditorEditPage}/>
        <Route path="/editor" component={EditorListPage}/>
      </Switch>
    </Route>
  )}
  
  {/* Subscriber Routes */}
  {getRoles.some(
     item => ["SUB_PERVIEW", "SUB_SUBSCRIPTION", "SUB_FREE"].includes(item)
   ) && (
    <Route path="/content" component={ContentPage}/>
  )}

  <Route path="/404" component={NotFoundPage}/>
  <Redirect to="/404"/>
</Switch>

您可以简单地定义一个受保护的路由组件并重用它:

import React from "react";
import { Route, Redirect } from "react-router-dom";

const isContributor = localStorage.getItem("roles") && localStorage.getItem("roles").split(",").includes("CONTRIBUTOR");

const ProtectedRoute = ({ component: Component, ...rest }) => {

  return (
    <Route
      {...rest}
      render={(props) =>
        isContributor ? <Component {...props} /> : <Redirect to="/404" />
      }
    />
  );
};

然后按如下方式使用该路线:

 <ProtectedRoute exact path="/editor" component={EditorListPage}/>