【问题标题】:How to nest routes in React Router v4?如何在 React Router v4 中嵌套路由?
【发布时间】:2017-07-04 10:35:46
【问题描述】:

有没有办法在 React Router v4 中嵌套路由?

这行得通:

  <Router basename='/app'>
    <main>
      <Route path='/' component={AppBar} />
      <Route path='/customers' component={Customers} />
    </main>
  </Router>

这不是:

  <Router basename='/app'>
    <Route path='/' component={AppBar}>
      <Route path='/customers' component={Customers} />
    </Route>
  </Router>

客户组件:

import React, { Component, PropTypes } from 'react'
import styled from 'styled-components'

export default class Customers extends Component {
  render () {
    return (
      <Container>
        <h1>Customers</h1>
      </Container>
    )
  }
}

const Container = styled.section`
  height: 100%;
  padding: 15px;
  overflow: auto;
`

【问题讨论】:

  • @ExperimentsWithCode,我主要是想看看是否有办法避免需要包装器(即&lt;main&gt;),因为&lt;Router&gt; 只能有一个孩子。
  • 您是否遇到错误,因为我完全按照您的“没有”做,而且效果很好。
  • 在第二个例子中,Customers 组件没有渲染。
  • 您可以发布您的客户组件吗?
  • @ExperimentsWithCode,已发布。

标签: reactjs react-router react-router-v4


【解决方案1】:

迄今为止我发现的最佳模式。

// main app
<div>
    // not setting a path prop, makes this always render
    <Route component={AppShell}/>
    <Switch>
        <Route exact path="/" component={Login}/>
        <Route path="/dashboard" component={AsyncDashboard(userAgent)}/>
        <Route component={NoMatch}/>
    </Switch>
</div>

我可以继续将它嵌套在一个组件中,一切都很好,包括 hmr(如果使用 webpack,不要忘记将 output.publicPath 设置为 "/"

// dashboard component
<div>
    // the same way as before, not setting a path prop
    // makes it render on every /dashboard/** request 
    <Route component={DashboardTAB}/>
    <Switch>
        // longer path (with same root) than others first
        <Route path="/dashboard/graphs/longerpath" component={GraphForm}/>
        <Route path="/dashboard/graphs" component={Graphs}/>
        <Route path="/dashboard/workers" component={List}/>
        <Route path="/dashboard/insert" component={InsertComponent}/>
    </Switch>
</div>

【讨论】:

  • 我确实喜欢这样,但是使用主父布局,它可以正常运行而没有错误,但仅在 中显示第一条路线(在组件中),当我单击链接时没有页面更改,我也在使用 webpack 并按照你所说的放置 output.publicPath .. 对另一个问题有什么想法吗?谢谢
  • 完美没关系,我刚刚开始了最短路径的第一条路线,因此将最短路径作为唯一可用的路径。
  • Not setting path prop 解决了我遇到的问题。谢谢!
【解决方案2】:

我从文档中改编了这个,到目前为止似乎有效。可能遗漏了一些明显的东西,是的,这不是 v4 方式,但我们需要在一个地方定义所有路由。

function RouteNest(props){ return (
  <Route exact={props.exact} path={props.path} render={ p => <props.component {...p} children={props.children}/> } />
)}

export const MainRoutes = props => 

<div className='content layout'>

  <Route exact path="/" component={Landing}/>
  <Route  path={'/contact'} component={Contact}/>

  <RouteNest  path={'/thing'} component={CompoWithSub}>
    <RouteNest  path={'/thing/suba'} component={SubComponentA}/>
    <RouteNest  path={'/thing/subb'} component={SubComponentB}/>
  </RouteNest>


</div>

export const CompoWithSub = props => <div>{props.children)</div>

【讨论】:

    【解决方案3】:

    你的 AppBar 组件负责渲染客户。对于要调用的客户,您必须渲染 AppBar 的子项。任何直接嵌套在 AppBar 下的东西都是 AppBar 的子项。

    import React from 'react';
    
    const AppBar = ({ children }) => (
      <div>
        <header>
           <h1> stuff </h1>
        </header>
        {children}
      </div>
    );
    
    export default AppBar
    

    请注意,当您访问“/”时,只有 AppBar 会呈现。 AppBar 和 Customers 将在您访问“/customers”时呈现。

    【讨论】:

    • 即使渲染 &lt;AppBar /&gt;{ children },当嵌套在 React Router v4 中时,&lt;Customers /&gt; 组件也不会渲染。
    • 你在网址“/customers”?
    • 是的。 /app/customers。如果没有嵌套,&lt;Customers /&gt; 组件会在该 URL 处呈现。
    • 好吧。我以为我在v4上,但我在v3上。对于那个很抱歉。不确定这两个版本之间有什么变化。
    • 文档中对嵌套路由的唯一引用是:reacttraining.com/react-router/#match 但我只是不明白它如何用于构建嵌套路由。
    【解决方案4】:

    如果有人想要嵌套路由而不输入包装路由的前缀,我在 TSX 中创建了类似的东西:

    进口:

    import * as React from 'react';
    import { Route, RouteComponentProps, RouteProps, Switch } from 'react-router-dom';
    import Index from 'views/index';
    import Login from 'views/login';
    import NoMatch from 'views/no-match';
    

    接口:

    interface INestedRoutes {
        nested?: string;
    }
    
    interface INestedRoute extends RouteProps, INestedRoutes {}
    

    NestedRoute 和 NestedRoutes 包装器:

    class NestedRoutes extends React.Component<INestedRoutes> {
        public render() {
            const childrenWithProps = React.Children.map(this.props.children, (child) => {
                return React.cloneElement(
                    child as React.ReactElement<any>, { nested: this.props.nested },
                );
            })
            return childrenWithProps;
        }
    }
    
    
    const NestedRoute: React.SFC<INestedRoute> = (props: INestedRoute) => {
        return <Route path={`${props.nested}${props.path}`} component={props.component} />;
    };
    

    以及带有包装器的路由:

    const MultiLanguage: React.SFC<RouteComponentProps<any>> = (props: RouteComponentProps<any>) => {
        return (
            <NestedRoutes nested={props.match.path} >
                <NestedRoute path="/test" component={Login} />
                <NestedRoute path="/no-match" component={NoMatch} />
            </NestedRoutes>
        );
    };
    
    
    export default (
        <Switch>
            <Route path="/:language" component={MultiLanguage}/>
            <Route exact={true} path="/" component={Index} />
            <Route path="/login" component={Login} />
            <Route component={NoMatch} />
        </Switch>
    );
    

    【讨论】:

      【解决方案5】:

      对于嵌套路由,我使用了一种非常简单的方法。

      示例主路由器是这样的

      <Router history={history}>
        <Switch >
          <Route path="/" component={Home}></Route>
        </Switch>
      </Router>
      

      使用嵌套路由的内部 Home 组件如下:

      <div className="App">
        <Navbar title="Home" links = { NavbarLinks }/>
        {this.renderContentPage()}
      </div>
      

      renderContentPage 将检查 URL 并渲染嵌套路由。

      <Route exact path="/" component={Page1}></Route>
      <Route exact path="/page1" component={Page1}></Route>
      <Route exact path='/page2' component={Page2} />
      

      所以在 Home 组件 page1 和 page2 组件内渲染。

      【讨论】:

        【解决方案6】:

        Route 需要一个子组件,即一个组件。 它不应该是一条新路线。 您可以做的是将您的嵌套路由包含在您的客户组件中。

        还要确保删除客户组件中的确切路线。

        【讨论】:

          猜你喜欢
          • 2017-11-11
          • 2017-08-28
          • 2017-06-25
          • 2019-01-07
          • 1970-01-01
          • 1970-01-01
          • 2017-10-05
          • 2017-08-16
          相关资源
          最近更新 更多