web-dev-qa-db-fra.com

React Router v4 itinéraires imbriqués props.children

Je suis en train de mettre à jour mon application universelle Redux pour utiliser Réagir Routeur v4. J'ai imbriqué des routes sous une route de mise en page principale. Auparavant, j'utilisais {props.children} pour afficher le contenu des itinéraires enfants, mais cela ne fonctionne plus. Comment ça marche en V4? 

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

ou 

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

Voici à quoi ressemble mon fichier de mise en page

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

J'ai pris le <Provider>out car il appartient à react-redux et vous n'en avez pas besoin comme base de routage avec react-router (de toute façon, vous pouvez facilement l'ajouter en encapsulant la structure).

Dans React Router V4, ce qui était Router a été renommé BrowserRouter et importé du package react-router-dom. Donc, pour les itinéraires de nidification, vous devez l'insérer en tant qu'enfant de votre <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;

Prenez en compte que cela ne fonctionne que pour le Web. L'implémentation native diffère.
J'ai téléchargé un petit projet basé sur Create React App où je montre l'implémentation des routes imbriquées dans la V4.

23
Dez

Je pensais juste que je devais partager cela. Si vous utilisez un composant Link dans votre composant Header. La réponse ci-dessus ne fonctionnera pas. Il vous faudrait redéfinir la BrowserRouter en tant que parent pour prendre en charge Link. Faites comme ça:

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

Je voudrais utiliser cette structure, sans 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'))
2
zarcode

S'il vous plaît lire ce blog à travers. https://codeburst.io/react-router-v4-unofficial-migration-guide-5a370b8905a

Non plus <IndexRoute>

Le composant autorisé à router vers un composant donné sur un chemin de niveau supérieur dans la 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>
)

Ce composant n'existe plus dans la v4. Pour le remplacer, utilisez une combinaison de, exact et commande d'itinéraires (en plaçant l'itinéraire index en dernier):

  // 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>
);
1
Kiry Meas

Ajout à la réponse @Dez

Mise en œuvre complète en natif/avec la prise en charge de 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);
1
Vivek Bharatha

Si vous utilisez avec Redux, sans l’élément 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;

Fournisseur placé dans la fonction de rendu

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'));
0
Homam Bahrani