React Router v4 嵌套路由 props.children
Posted
技术标签:
【中文标题】React Router v4 嵌套路由 props.children【英文标题】:React Router v4 nested routes 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>
);
【问题讨论】:
【参考方案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
没有了
<IndexRoute>
在 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】:我采用了<Provider>
out,因为它属于react-redux
,并且您不需要它作为使用react-router
进行路由的基础(无论如何您可以轻松地添加它来封装结构)。
在 React Router V4 中,Router
已重命名为 BrowserRouter
并从包 react-router-dom
中导入。因此,对于嵌套路由,您需要将其作为 <Layout>
的子级插入。
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 的回复,我改变了我的结构。部分问题在于它是一个通用应用程序,所有路由都需要在IndexRoute
在 React Router 4 中不再可用。您在此处有 RR4 文档:reacttraining.com/react-router/web/guides/philosophy跨度>
@Dez 抱歉不得不删除评论来更新它,没有注意到你已经回答它被隐藏了。如果不使用父 div 并在 </BrowserRouter>
内使用 <Route path="/" component=Layout>
和 <IndexRoute component=Home/>
,无论是否有包装 div,我都无法让子路由以旧方式工作。我想要加载一个布局,以及在给定路线的布局内加载的路线。关于这部分,我不清楚文档。有没有更多的文档?以上是关于React Router v4 嵌套路由 props.children的主要内容,如果未能解决你的问题,请参考以下文章