React Router v4 вложенные маршруты props.children
Я обновляю приложение универсального реагирования redux, чтобы использовать реактивный маршрутизатор 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
Я выбрал <Provider>
, потому что он принадлежит 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')
);
Layout.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, где я показываю реализацию вложенных маршрутов в V4.
Ответ 2
Просто подумал, что я должен поделиться этим. Если вы используете компонент Link
в своем компоненте Header
. Ответ выше не будет работать. Вам нужно будет вернуть BrowserRouter
в качестве родителя для поддержки Link
. Сделайте это так:
<BrowserRouter>
<Layout>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/other" component={OtherComponent} />
<Route component={Error404} />
</Switch>
</Layout>
</BrowserRouter>
Ответ 3
Я бы использовал эту структуру без реквизитов.
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
Добавление в ответ @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);
Ответ 5
Прочтите этот блог. 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. Чтобы заменить его, используйте комбинацию, точное и маршрутное упорядочение (поместите последний маршрут указателя):
// 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>
);
Ответ 6
Если вы используете с 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;
Layout.js
const Layout = props => ({
render() {
return (
<div className="container">
<Header />
<main>{props.children}</main>
<Footer />
</div>
);
}
});
export default Layout;
Поставщик размещен в функции 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'));