简体   繁体   English

如何使用 React 路由器嵌套路由

[英]How do I nest routes with React router

I have multiple layouts that should include different screens.我有多个布局,应该包括不同的屏幕。 Each layout has its own header, footer, and other things similar pages should share.每个布局都有自己的 header、页脚和其他类似页面应该共享的内容。 Here is the code I came up with:这是我想出的代码:

<BrowserRouter>
  <Route path={['/index', '/about']} component={BaseLayout}>
    <Route path="/index" component={Index} />
    <Route path="/about" component={About} />
  </Route>
  <Route path={['/sign-in', '/sign-up']} component={AuthLayout}>
    <Route path="/sign-in" component={SignIn} />
    <Route path="/sign-up" component={SignUp} />
  </Route>
  <Route path={['/stats'} component={DashboardLayout}>
    <Route path="/stats" component={Stats} />
  </Route>
</BrowserRouter>

The code above obviously won't work because:上面的代码显然不起作用,因为:

Warning: You should not use <Route component> and in the same route;警告:你不应该使用<Route component>并且在同一个路由中; <Route component> will be ignored <Route component>将被忽略

Answers to similar questions on SO suggest to use wrapper components directly: SO上类似问题的答案建议直接使用包装器组件:

<BrowserRouter>
  <BaseLayout>
    <Route path="/index" component={Index} />
    <Route path="/about" component={About} />
  </BaseLayout>
  <AuthLayout>
    <Route path="/sign-in" component={SignIn} />
    <Route path="/sign-up" component={SignUp} />
  </AuthLayout>
  <DashboardLayout>
    <Route path="/stats" component={Stats} />
  </DashboardLayout>
</BrowserRouter>

Problem with this approach is that even that it renders a single screen, it also renders elements from the other layouts, ie if you're on the index page rendered inside the BaseLayout , you will see elements from the AuthLayout and DashboardLayout too.这种方法的问题在于,即使它呈现单个屏幕,它也会呈现来自其他布局的元素,即,如果您在BaseLayout内呈现的索引页面上,您也会看到来自AuthLayoutDashboardLayout的元素。 Which kinda makes sense because they are not wrapped in a Route .这有点道理,因为它们没有被包裹在Route中。

Some people suggested to grab the content of all layouts and add them as siblings to the current Routes.有人建议抓取所有布局的内容并将它们作为兄弟姐妹添加到当前路由中。 However this is a mess to me.然而,这对我来说是一团糟。 I do want to keep all layouts in separate files and only pass screens as children to them.我确实想将所有布局保存在单独的文件中,并且只将屏幕作为子项传递给它们。

This is a rough draft of a potential layout structure:这是潜在布局结构的粗略草图:

<Header>
  <Router>
    <Router path={['/index', '/about']} component={HeaderComponent} />
    <Router path={['/sign-in', '/sign-up']} component={AuthHeaderComponent} />
  </Router>
</Header>
<Screens>
  <Router>
    <Route path="/index" component={BaseLayout(Index)} />
    <Route path="/about" component={BaseLayout(About)} />
    <Route path="/sign-in" component={AuthLayout(SignIn)} />
    <Route path="/sign-up" component={AuthLayout(SignUp)} />
    <Route path="/stats" component={DashboardLayout(Stats)} />
  </Router>
</Screens>
<Footer>
  <FooterComponent />
</Footer>

In this example the wrappers are HOCs so they can handle passing all props from the route down to the page component, but if you just wanted to do an inline wrapper you could use the render function:在此示例中,包装器是 HOC,因此它们可以处理将所有道具从路由向下传递到页面组件,但如果您只想做一个内联包装器,您可以使用渲染function:

<Route
  path="/index"
  render={routeProps => {
    return (
      <BaseLayout>
        <Index {...routeProps}/>
      </BaseLayout>
    );
  }}
/>

[edit] A sample Layout HOC ( docs ) [编辑] 一个示例布局 HOC(文档

const withBaseLayout = WrappedComponent => {
  // any business logic required for the layout
  // layoutProps, style, etc...
  return (
    <BaseLayout {...layoutProps}>
      <WrappedComponent {...this.props} /> // these are all the passed in props
      // you can inject more props into Wrapped component as well
      // i.e. redux's connect or react-router-dom's withRouter HOCs
    </BaseLayout>
  );
}

// in index.js
export default withBaseLayout(Index);

// in route
<Route path="/index" component={Index} /> // already wrapped

Or directly as Component或者直接作为组件

const BaseLayoutHOC = WrappedComponent => {
  // any business logic required for the layout
  // layoutProps, style, etc...
  return (
    <BaseLayout {...layoutProps}>
      <WrappedComponent {...this.props} />
    </BaseLayout>
  );
}

// in route
<Route path="/index" component={BaseLayoutHOC(Index)} />

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

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