2017-05-31 1 views
2

Bei meinem Versuch geschachtelte Routen zu tun, habe ich nicht die Kind-Komponenten zu mounten, wenn die Route ändert sich über Link oder history.push; Aber wenn die Routen direkt in der Datei root.js deklariert werden, funktioniert es. Idealerweise möchte ich so viele Routen wie möglich in der Datei root/routes.js und nicht in der gesamten App verwalten (ich übergebe stattdessen das root/routes.js-Objekt, um dies automatisch zu tun; ich meine ... versuchen)Router 4 Verschachtelung Routen alternative Technik

To break it down logically (it's a bit abstract, but check the code below afterwards please): 
- There's a `root/routes.js` that has all the routes configuration (parents, nested components, etc) 
- The `root.js` defines the `<Route...>` where the attribute `component` is the return value of a function that passes the `routes` configuration to its `routes` component prop 
- the main wrapper iterates over the component prop `routes` and defines `child` routes automatically...I mean...I'm trying... 

Warum sollte ich das tun? Wie funktioniert mein Gehirn und warum nicht? War möglich, bevor reagieren Router 4

<MyAppWrapper> 
<CommonNavigationBar /> 
<Main> 
    ----- dynamic/changes by route etc ----- 
</Main> 
<Footer /> 
</MyAppWrapper> 

Ich frage mich, wo mein Versuch scheitert?

// Working version 
import React from 'react' 
import { Route } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import rootRoutes from './routes' 
import App from '../app/containers/app' 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     <Route path='/' component={App} /> 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root 

Für das vorherige Beispiel, wie verschachtelt die App Komponente, unten Ich versuche, das zu tun dynamically..and es nicht aus irgendeinem Grunde! Es sollte genau obwohl die gleichen sein ... es irgendwo eine typoe sein muss ...

wie

import React, { Component } from 'react' 
import { isBrowser } from 'reactatouille' 
import { connect } from 'react-redux' 
import { bindActionCreators } from 'redux' 
import { withRouter, Route } from 'react-router' 
import Navbar from '../navbar' 
import JourneySelector from '../journeySelector' 
import reservationFinder from '../../../reservationFinder' 

// include the stylesheet entry-point 
isBrowser() && require('../../../../sass/app.scss') 

class App extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { 
     init: true 
    } 
    } 

    render() { 
    return (
     <div className={'app' + ' ' + (!this.state.init && 'uninitialised')}> 
     <Navbar /> 
     <main> 
      <Route exact path='/' component={JourneySelector} /> 
      <Route exact path='/reservation-finder' component={reservationFinder.containers.App} /> 
     </main> 
     </div> 
    ) 
    } 
} 

// export default App 
function mapStateToProps (state, ownProps) { 
    return { 
    // example: state.example 
    } 
} 

function matchDispatchToProps (dispatch) { 
    return bindActionCreators({ 
    // replay: replay 
    }, dispatch) 
} 

export default connect(mapStateToProps, matchDispatchToProps)(withRouter(App)) 

Während meine Technik versagt (alles, was ich zu tun bin versucht, die root/Routen iterieren Kinder leitet diese zu erzeugen):

// root/routes.js 
import app from '../app' 
import reservationFinder from '../reservationFinder' 

const rootRoutes = [ 
    { 
    path: '/', 
    component: app.containers.App, 
    exact: true, 
    routes: [{ 
     path: '/', 
     exact: true, 
     component: app.containers.JourneySelector 
    }, { 
     path: '/reservation-finder', 
     component: reservationFinder.containers.App 
    }] 
    } 
] 

export default rootRoutes 

Die Wurzel js Datei. Sie sehen die setRoute Fn gibt eine neue Komponente, wo die Kinder Routen als props übergeben wird? Ich glaubte, dies funktionieren würde:

// root.js 
import React from 'react' 
import { Route, Switch } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import rootRoutes from './routes' 

const setRoute = (route) => { 
    const MyComponent = route.component 
    return <Route key={route.path} exact={route.exact || false} component={() => (<MyComponent routes={route.routes} />)} /> 
} 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     { rootRoutes.map(route => setRoute(route)) } 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root 

die wichtigsten app, die ich als Wrapper verwenden möchten:

// main app 
import React, { Component } from 'react' 
import { isBrowser } from 'reactatouille' 
import { connect } from 'react-redux' 
import { bindActionCreators } from 'redux' 
import { withRouter, Route } from 'react-router' 
import Navbar from '../navbar' 

// include the stylesheet entry-point 
isBrowser() && require('../../../../sass/app.scss') 

class App extends Component { 
    constructor (props) { 
    super(props) 
    this.state = { 
     init: true 
    } 
    } 

    render() { 
    return (
     <div className={'app' + ' ' + (!this.state.init && 'uninitialised')}> 
     <Navbar /> 
     <main> 
      { Array.isArray(this.props.routes) && this.props.routes.map(route => <Route key={route.path} {...route} />) } 
     </main> 
     </div> 
    ) 
    } 
} 

// export default App 
function mapStateToProps (state, ownProps) { 
    return { 
    // example: state.example 
    } 
} 

function matchDispatchToProps (dispatch) { 
    return bindActionCreators({ 
    // replay: replay 
    }, dispatch) 
} 

export default connect(mapStateToProps, matchDispatchToProps)(withRouter(App)) 

ich ich mag wie etwas in der Lage zu verstehen ähnlich, erreichen ?!

// root 
import React from 'react' 
import { Route, Switch } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import rootRoutes from './routes' 
import MyAppWrapper from 'xxx/MyAppWrapper'  

const setRoute = (route) => { 
    const MyComponent = route.component 
    return <Route key={route.path} exact={route.exact || false} component={() => (<MyComponent routes={route.routes} />)} /> 
} 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     <MyAppWrapper> 
      <Route path='x' component={x} /> 
      <Route path='y' component={y} /> 
     </MyAppWrapper> 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root 

Hinweise: Während des Tests habe ich festgestellt, dass es serverseitig funktioniert? Ich meine, ich habe etwas verpasst, und ich habe meine Arbeit nicht gerettet. Auch , wenn es fehlschlägt, die vorherige Komponente (der Standard) ist nach wie vor angebracht und nicht aushängen nicht

Ich habe sogar versucht (ohne Erfolg ... Ich frage mich, ob dies ist ein Bug):

import React from 'react' 
import { Route } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import App from '../app/containers/app' 
import rootRoutes from './routes' 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     <Route path='/' render={() => (
      <App /> 
     )} /> 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root 

Ok, ich denke, das ist ein Fehler, der gemeldet wurde (https://github.com/ReactTraining/react-router/issues/5190). Sie können das Live-Beispiel hier finden (https://codepen.io/helderoliveira/pen/rmXdgd), klicken Sie auf topic. Vielleicht wird das, was ich versuche, nicht unterstützt, aber statt leer sollten wir eine Fehlermeldung erhalten.

Antwort

1

Ok, ich habe den Tippfehler gefunden. Die Lösung ist es, render und übergeben Sie die RouterProps + andere Requisiten, die Sie wünschen, durch Object.assign und den Spread-Operator!

// root.js 
import React from 'react' 
import { Route } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import App from '../app/containers/app' 
import rootRoutes from './routes' 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     <Route path='/' render={routeProps => <App {...Object.assign({}, routeProps, { routes: rootRoutes[0].routes })} />} /> 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root 

Und die Haupt App-Wrapper:

class App extends Component { 
    render() { 
    return (
     <div className={'app kiosk' + ' ' + (!this.state.init && 'uninitialised')}> 
     <Navbar /> 
     <main> 
      { Array.isArray(this.props.routes) && this.props.routes.map(route => <Route key={route.path} exact={route.exact} path={route.path} component={route.component} />) } 
     </main> 
     </div> 
    ) 
    } 
} 

export default App 

die Routen-Datei:

import React from 'react' 
import { Route } from 'react-router' 
import { BrowserRouter } from 'react-router-dom' 
import { Provider } from 'react-redux' 
import rootRoutes from './routes' 

const setRoute = (route) => { 
    const MyComponent = route.component 
    return <Route key={route.path} path={route.path} render={routeProps => <MyComponent {...Object.assign({}, routeProps, { routes: rootRoutes[0].routes })} />} /> 
} 

const Root = ({store, history}) => { 
    return (
    <Provider store={store}> 
     <BrowserRouter history={history}> 
     <div> 
      { rootRoutes.map(route => setRoute(route)) } 
     </div> 
     </BrowserRouter> 
    </Provider> 
) 
} 

export default Root