简体   繁体   English

react router dom v5中的嵌套路由和未找到路由

[英]Nested routes and not found route in react router dom v5

While trying to make nested routes in react router dom v5 I found this answer that explains how to do it very well在尝试在反应路由器 dom v5 中创建嵌套路由时,我发现这个答案解释了如何很好地做到这一点

(please take a look at the code here because it's a little bit difference from the answer mentioned above) (请看这里的代码,因为它与上面提到的答案有点不同)

Layouts.js布局.js

const NotFound = () => <h1>Not Found</h1>;

function Layouts() {
  return (
    <Switch>
      <Route path="/auth" component={AuthLayout} />
      <Route path="/app" component={AppLayout} />
      <Route path="/" component={NotFound} />
    </Switch>
  );
}

AuthLayout授权布局

const Signup = () => <p>Login</p>;
const Login = () => <p>Sign up</p>;

function AuthLayout() {
  return (
    <div>
      <h1>Auth Layout</h1>
      <Route path="/auth/signup" exact component={Signup} />
      <Route path="/auth/login" exact component={Login} />
      {/* Commenting this because I want to go to NotFound component */}
      {/* <Redirect from="/auth" to="/auth/login" exact /> */}
    </div>
  );
}

AppLayout应用布局

const Home = () => <p>Home</p>;
const Dashboard = () => <p>Dashboard</p>;

function AppLayout() {
  return (
    <div>
      <h1>App Layout</h1>
      <Route path="/app/home" exact component={Home} />
      <Route path="/app/dashboard" exact component={Dashboard} />
      {/* Commenting this because I want to go to NotFound component */}
      {/* Redirect from="/app" to="/app/home" exact /> */}
    </div>
  );
}

But this have one problem, that if you go to a route with /app/somethingnotfound it won't go to <Route path="/" component={NotFound} /> , it will "stay inside" AppLayout and render no route.但这有一个问题,如果你 go 到带有/app/somethingnotfound的路由,它不会 go 到<Route path="/" component={NotFound} /> ,它将“留在里面” AppLayout并且不渲染路由.

How can I make /app/somethingnotfound go to <Route path="/" component={NotFound} /> in this case?在这种情况下,如何将/app/somethingnotfound go 设置为<Route path="/" component={NotFound} />

Edit:编辑:

Just to be more clear: I don't want to just add <Route component={NotFound} /> inside AuthLayout and AppLayout because it will render other things.更清楚一点:我不想在AuthLayoutAppLayout中添加<Route component={NotFound} />因为它会渲染其他东西。 What I really need is to show the top level NotFound .我真正需要的是展示顶级NotFound

Not found component usually works like this:未找到的组件通常是这样工作的:

<Router>
  <Switch>
    <Route exact path="/auth" component={AuthLayout} />
    <Route exact path="/app" component={AppLayout} />
    <Route component={NotFound} />
  </Switch>
</Router>

But you cannot mark /auth and /app as exact as they contain nested routes.但是您不能将/auth/app标记为exact ,因为它们包含嵌套路由。 So, you should do:所以,你应该这样做:

<Router>
  <Switch>
    <Route path="/auth" component={AuthLayout} />
    <Route path="/app" component={AppLayout} />
    <Route exact path="/404" component={NotFound} />
    <Redirect to='/404' />
  </Switch>
</Router>

and your component (eg AppLayout ) with nested routes:以及带有嵌套路由的组件(例如AppLayout ):

<>
<h1>App Layout</h1>
<Switch>
  <Route path="/app/home" exact component={Home} />
  <Route path="/app/dashboard" exact component={Dashboard} />
  <Redirect to="/404" />
</Switch>
</>

While looking in github issues I found out this solution , you create a "global not found page" where you pass through the state if the route isn't found, and just render that instead of the other routes.在查看 github 问题时,我发现了这个解决方案,您创建了一个“全局未找到页面”,如果找不到路由,则在其中通过 state,然后只渲染它而不是其他路由。

const NotFound = () => <div className="not_found"><h1>Not Found</h1></div>;

const RouteNotFound = () => <Redirect to={{ state: { notFoundError: true } }} />;

const CaptureRouteNotFound = withRouter(({children, location}) => {
  return location && location.state && location.state.notFoundError ? <NotFound /> : children;
});

const Settings = () => {
  return (
    <Switch>
      <Route path="/settings/account" render={() => <h1>Account Settings</h1>} />
      <Route path="/settings/profile" render={() => <h1>Profile Settings</h1>} />

      <RouteNotFound />
    </Switch>
  );
};

const AppShell = ({children}) => {
  return (
    <div className="application">
      <header>Application</header>
      {children}
    </div>
  );
};

const Application = () => {
  return (
    <Router>
      <CaptureRouteNotFound>
        <AppShell>
          <Switch>
            <Route path="/settings" render={() => <Settings />} />
            <Route path="/profile" render={() => <h1>User Profile</h1>} />

            <RouteNotFound />
          </Switch>
        </AppShell>
      </CaptureRouteNotFound>
    </Router>
  );
};

<Route path="/" component={NotFound} /> doesn't match for all the nested that are not implemented, because the Switch in the Layouts component will only render the first Route child that matches the pathname . <Route path="/" component={NotFound} />不匹配所有未实现的嵌套,因为Layouts组件中的Switch只会渲染与pathname匹配的第一个Route子节点。 In your case, it matches the route with AppLayout component when you go the path /app/somethingdoesntexist that is why it only renders the AppLayout component.在您的情况下,当您 go 路径/app/somethingdoesntexist时,它将路由与AppLayout组件匹配,这就是它仅呈现AppLayout组件的原因。

Solution解决方案

It is better to implement a NotFound route for each layout using nested Switch components, For example最好使用嵌套的Switch组件为每个布局实现NotFound路由,例如

function AppLayout() {
  const { path, url } = useRouteMatch();

  return (
      <Switch>
        <Route path={`${path}/home`} exact component={Home} />
        <Route path={`${path}/dashboard`} exact component={Dashboard} />
        <Route path="*" component={NotFound} />
      </Switch>
  );
}

In the case above we got the matched path by using useRouteMatch hook and nest another Switch component that will render any nested route that matches from the path and we provide a fallback Route specifying the path as "*" which will render the NotFound component when there is no match found.在上面的例子中,我们通过使用useRouteMatch钩子获得了匹配的路径,并嵌套了另一个Switch组件,该组件将渲染与path匹配的任何嵌套路由,并且我们提供了一个备用Route ,将路径指定为"*" ,它将在存在时渲染NotFound组件没有找到匹配项。

Here is a complete example of the solution codesandbox .这是解决方案代码框的完整示例

You can also see the nesting example provided in the docs.您还可以查看文档中提供的嵌套示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM