2017-05-31 99 views
2

在我嘗試做嵌套路由時,我未能通過Link或history.push更改路由時要裝載子組件;但如果直接在root.js文件中聲明路由,它將起作用。所以,理想情況下,我希望在root/routes.js文件中保留儘可能多的路由配置,而不是遍佈整個應用程序(我遍歷根/ routes.js對象,而不是自動執行;我的意思是...試)React路由器4嵌套路由替代技術

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... 

我爲什麼要這樣做?我的大腦如何工作,爲什麼不呢?有可能之前,反應路由器4

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

我想知道我的嘗試失敗的地方?

// 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 

對於前面的示例,嵌套的應用程序組件,波紋管我試圖做到這一點dynamically..and它由於某種原因失敗!它應該是完全一樣的,但...必須有某處typoe ...

一樣,

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)) 

雖然我的技術故障(所有我想要做的就是迭代根/路線兒童路線生成這些):

// 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 

根js文件。你看到setRoute fn返回一個新組件,其中子路由作爲props傳遞?我相信這會工作:

// 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 

,我想作爲一個包裝使用的主要應用:

// 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)) 

我明白,我也許能達到類似的東西,像?

// 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 

注意:在測試過程中,我注意到它在服務器端工作?我的意思是,我可能錯過了一些東西,而且我沒有保存我的工作。此外,失敗時,前一個組件(默認)仍然安裝,並且不卸載

我甚至嘗試(不sucess ...我不知道這是否是一個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 

好吧,我認爲這是一個如此報道的錯誤(https://github.com/ReactTraining/react-router/issues/5190),你可以在這裏找到活的例子(https://codepen.io/helderoliveira/pen/rmXdgd),點擊topic。也許我試圖做的不支持,但不是空白,我們應該得到一個錯誤消息。

回答

1

好的,我發現了這個錯字。解決方法是使用渲染並通過Object.assign和spread運算符傳遞routerProps +任何其他需要的道具!

// 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 

和主要應用程序包裝:

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 

路由文件:

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