【问题标题】:React Router v4 nested routes props.childrenReact Router v4 嵌套路由 props.children
【发布时间】:2017-08-28 01:14:17
【问题描述】:

我正在更新我的通用 react redux 应用程序以使用 react router v4。我在主要布局路线下有嵌套路线。以前我使用 {props.children} 来显示子路由的内容,但这不再起作用了。这在 V4 中如何工作?

<Provider store={store} key="provider">
  <div>
    <Route component={Layout} />
    <Switch>
      <Route path="/" component={HomePage} />
      <Route component={Error404} />
    </Switch>
  </div>
</Provider>

或

<Provider store={store} key="provider">
  <Layout>
    <Route path="/" component={HomePage} />
    <Route component={Error404} />
  </Layout>
</Provider>

这就是我的布局文件的样子

const Layout = props => (
 <div className="o-container">
   <Header />
     <main>
      {props.children}
     </main>
   <Footer />
 </div>
);

【问题讨论】:

    标签: javascript reactjs react-router


    【解决方案1】:

    只是觉得我必须分享这个。如果您在 Header 组件中使用 Link 组件。上面的答案是行不通的。您必须再次将BrowserRouter 设为父级以支持Link。变成这样:

    <BrowserRouter>
     <Layout>
      <Switch>
        <Route exact path="/" component={HomePage} />
        <Route path="/other" component={OtherComponent} />
        <Route component={Error404} />
      </Switch>
     </Layout>
    </BrowserRouter>
    

    【讨论】:

    • 如果他们尝试这样做,这对于任何发现问题的人来说都是一个好点。 OP 起初只是想将路线加载为他的布局的子项。
    【解决方案2】:

    请仔细阅读此博客。 https://codeburst.io/react-router-v4-unofficial-migration-guide-5a370b8905a

    没有了&lt;IndexRoute&gt;

    在 v3 中允许路由到顶级路径上的某个组件的组件:

    // in src/MyApp.js
    const MyApp = () => (
        <Router history={history}>
            <Route path="/" component={Layout}>
                <IndexRoute component={Dashboard} />
                <Route path="/foo" component={Foo} />
                <Route path="/bar" component={Bar} />
            </Route>
        </Router>
    )
    

    这个组件在 v4 中不再存在。要替换它,请结合使用 、exact 和 route ordering(将索引路由放在最后):

      // in src/MyApp.js
    const MyApp = () => {
        <Router history={history}>
            <Route path="/" component={Layout} />
        </Router>
    }
    // in src/Layout.js
    const Layout = () => (
        <div className="body">
            <h1 className="title">MyApp</h1>
            <div className="content">
                <Switch>
                    <Route exact path="/foo" component={Foo} />
                    <Route exact path="/bar" component={Bar} />
                    <Route exact path="/" component={Dashboard} />
                </Switch>
            </div>
        </div>
    );
    

    【讨论】:

    • 如果索引路由是精确的,那你为什么要把它放在最后呢?
    • IMO 放在最后还是第一个都没关系。
    【解决方案3】:

    我会使用这种结构,没有 props.children :

    const Main = () => (
      <main>
        <Switch>
          <Route exact path="/" component={HomePage} />
          <Route component={Error404} />
        </Switch>
      </main>
    )
    
    const Layout = () => (
      <div>
        <Header />
        <Main />
        <Footer />
      </div>
    )
    
    ReactDOM.render((
        <Provider store={store}>
          <BrowserRouter>
            <Layout />
          </BrowserRouter>
       </Provider>
    ), document.getElementById('root'))
    

    【讨论】:

      【解决方案4】:

      如果与 Redux 一起使用,则不带 Switch 元素

      AppRouter.js

      import React from 'react'
      import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
      
      
      
      const AppRouter = () => (
        <Layout>
          <Router>
            <div>
              <nav>
                <ul>
                  <li><Link to="/">Home</Link></li>
                  <li><Link to="/about">About</Link></li>
                  <li><Link to="/contact">Contact</Link></li>
                </ul>
              </nav>
              <Route exact path="/" component={Home}/>
              <Route path="/about" component={About}/>
              <Route path="/contact" component={Contact}/>
            </div>
          </Router>
        </Layout>
      )
      
      export default AppRouter;
      

      布局.js

      const Layout = props => ({
        render() {
          return (
            <div className="container">
              <Header />
              <main>{props.children}</main>
              <Footer />
            </div>
          );
        }
      });
      
      export default Layout;
      

      Provider 放置在 Render 函数中

      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import { createStore, applyMiddleware } from 'redux';
      
      
      import AppRouter from './AppRouter';
      import reducers from './reducers';
      
      const createStoreWithMiddleware = applyMiddleware()(createStore);
      
      ReactDOM.render(
        <Provider store={createStoreWithMiddleware(reducers)}>
          <AppRouter />
        </Provider>
        , document.getElementById('app'));
      

      【讨论】:

        【解决方案5】:

        添加到@Dez 答案

        完整的原生/核心实现,支持 Redux

        index.js

        import React from 'react';
        import ReactDOM from 'react-dom';
        import { Provider } from 'react-redux';
        import { Router, Route, Switch } from 'react-router';
        import createMemoryHistory from 'history/createMemoryHistory';
        
        const history = createMemoryHistory();
        
        import App from './components/App';
        import Home from './components/Home';
        import Login from './components/Login';
        import store from './store';
        
        ReactDOM.render((
          <Provider store={ store }>
            <Router history={history}>
              <App>
                <Switch>
                  <Route exact path="/" component={Home} />
                  <Route path="/login" component={Login} />
                </Switch>
              </App>
            </Router>
          </Provider>
        ), document.getElementById('root'));
        

        App.js

        import Header from './Header';
        import Home from './Home';
        import React from 'react';
        import {connect} from 'react-redux';
        
        const mapStateToProps = state => ({appName: state.appName});
        
        class App extends React.Component {
          render() {
            return (
              <div >
                <Header appName={this.props.appName} /> {/*common header*/}
                {this.props.children}
              </div>
            );
          }
        }
        
        export default connect(mapStateToProps, () => ({}))(App);
        

        【讨论】:

          【解决方案6】:

          我采用了&lt;Provider&gt;out,因为它属于react-redux,并且您不需要它作为使用react-router 进行路由的基础(无论如何您可以轻松地添加它来封装结构)。

          在 React Router V4 中,Router 已重命名为 BrowserRouter 并从包 react-router-dom 中导入。因此,对于嵌套路由,您需要将其作为 &lt;Layout&gt; 的子级插入。

          index.js

          import { Switch, Route } from 'react-router';
          import { BrowserRouter } from 'react-router-dom';
          import Layout from './Layout';
          ...
          const Root = () => (
            <Layout>
              <BrowserRouter>
                <Switch>
                  <Route exact path="/" component={HomePage} />
                  <Route path="/other" component={OtherComponent} />
                  <Route component={Error404} />
                </Switch>
              </BrowserRouter>
            </Layout>
          );
          
          ReactDOM.render(
            <Root/>,
            document.getElementById('root')
          );
          

          布局.js

          import React from 'react';
          import Header from './Header';
          import Footer from './Footer';
          
          const Layout = props => ({
            render() {
              return (
                <div className="o-container">
                  <Header />
                  <main>{props.children}</main>
                  <Footer />
                </div>
              );
            }
          });
          
          export default Layout;
          

          考虑一下,这仅适用于网络。本机实现不同。
          我在 Create React App 中上传了 a small project,我在其中展示了 V4 中嵌套路由的实现。

          【讨论】:

          • 感谢@Dez 的回复,我改变了我的结构。部分问题在于它是一个通用应用程序,所有路由都需要在 中,以及客户端的 中。当我包含来自 react-router-dom 的链接时,我仍然在服务器上收到错误
          • @blamb 正如在这个问题的答案stackoverflow.com/a/44799564/305953 中所说,IndexRoute 在 React Router 4 中不再可用。您在此处有 RR4 文档:reacttraining.com/react-router/web/guides/philosophy跨度>
          • @Dez 抱歉不得不删除评论来更新它,没有注意到你已经回答它被隐藏了。如果不使用父 div 并在 &lt;/BrowserRouter&gt; 内使用 &lt;Route path="/" component={Layout}&gt; 和 &lt;IndexRoute component={Home}/&gt;,无论是否有包装 div,我都无法让子路由以旧方式工作。我想要加载一个布局,以及在给定路线的布局内加载的路线。关于这部分,我不清楚文档。有没有更多的文档?
          猜你喜欢
          • 2019-01-07
          • 2017-06-25
          • 2017-11-11
          • 1970-01-01
          • 2017-10-05
          • 2017-07-04
          • 1970-01-01
          • 2018-06-06
          相关资源
          最近更新 更多