2017-11-17 42 views
1

我正在重構從React Router的V2到V4的應用程序,並且我遇到了一個問題,其中我的mapStateToProps的屬性沒有傳遞給每個組件。這裏是我的設置:OwnProps沒有通過React Router V4傳遞

App.jsx

render() { 
     return (
      <div> 
       <Header /> 
       <Navbar /> 
       <Routes {...this.props} /> 
       <Footer /> 
      </div> 
     ) 
    } 

const mapStateToProps = (state, ownProps) => { 
    const { page } = state 
    return { 
     routeProps: ownProps, 
     page: page 
    } 
} 

const mapDispatchToProps = (dispatch) => { 
    return { 
     pageActions: bindActionCreators(pageActionCreators, dispatch), 
    } 
} 

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

Routes.jsx了這一行:

<Route exact path="/:name/information" render={ ({ match }) => <InfoPage {...this.props} match={ match } /> } />

InfoPage.jsx

componentDidMount() { 
    const { routeProps, pageActions } = this.props 
    pageActions.fetchInfoPage(routeProps.match.params.name) 
} 
componentWillReceiveProps(nextProps) { 
    if (this.props.page.page !== nextProps.page.page) { 
     const { routeProps, pageActions } = nextProps 
     pageActions.fetchInfoPage(routeProps.match.params.name) 
    } 
} 
render() { 
    return (
     <InfoPageView 
     page={ this.props.page } 
     pageActions={ this.props.pageActions } 
     routeProps={ this.props.routeProps } 
     /> 
    ) 
} 

的問題是,當我嘗試訪問使用InfoPage的路線,即/orders/information從不加載。當我檢查Redux開發工具時,它說pagecontent未定義。在重構時我在InfoPage組件上更改的唯一東西是match.params而不是params。這讓我相信我的Redux/Router集成有些問題,特別是ownProps/routeProps沒有正確傳遞。

關於這裏有什麼問題的任何想法?

+0

什麼的休息Routes.jsx看起來像? – Calvin

+0

它有一個'Routes'類,它返回一個'',其中包含路由列表。前兩個爲: } />' – wildlifehexagon

回答

1

首先,確保你包裝Routes.jsx(正如@lemarc和@Kyle Richardson提到的那樣),以便您的路由組件能夠正確更新。

當您用withRouter包裝連接的組件時,它將使該組件的props中的match可用。

而不是試圖通過ownProps映射match,你可以從你的封裝組件的props訪問它。

此外,它看起來像你試圖引用綁定到您的子組件InfoPageViewApp組件的動作創建者。這是React + Redux應用程序中的反模式。

如果您的InfoPageView需要分派動作的能力,則應通過其自己的mapDispatchToProps函數直接將其提供給InfoPageView。您嘗試訪問的page屬性也是如此;如果InfoPageView需要讀取的page的價值,你應該通過mapStateToProps中直接提供:

import { Component } from 'react' 
import { connect, bindActionCreators } from 'react-redux' 
import { withRouter } from 'react-router' 
import { fetchInfoPage as fetchInfoPageAction } from '../actions/fetchInfoPage' 
//^import directly from wherever this Action Creator resides in your project^

class InfoPageView extends Component { 
    componentDidMount() { 

     const { match } = this.props 
     fetchInfoPage(match.params.name) // <-- `match` provided by withRouter() 

    } 

    componentWillReceiveProps(nextProps) { 

     if (this.props.page.page !== nextProps.page.page) { 
      const { match, fetchInfoPage } = nextProps 
      fetchInfoPage(match.params.name) // <-- `match` provided by withRouter() 
     } 

    } 
    render() { 

     return (
      <InfoPageView /> 
     ) 

    } 

} 

const mapStateToProps = (state) => ({ 
    page: state.page, 
    content: state.content, 
}) 
const mapDispatchToProps = (dispatch) => ({ 
    fetchInfoPage: bindActionCreators(fetchInfoPageAction, dispatch), 
}) 

export default withRouter(
    connect(mapStateToProps, mapDispatchToProps)(InfoPageView) 
) 

如果,畢竟,你會發現pagecontent仍然undefined,很可能是因爲他們只是從失蹤您的page減速機。驗證這些屬性出現在您page減速的initialState

const initialState = { page: 1, content: 'initial content' } 

const page = (state = initialState, action) => ({ 
    switch (action.type) { 

     // (action type `case` statements here) 

     default: 
      return state 
    } 
}) 

export default page 

...也驗證您是通過combineReducers傳遞page減速到你的店:

import pageReducer from '../reducers/page' 

const rootReducer = combineReducers({ 
    page: pageReducer, 
}) 

const store = configureStore(
    rootReducer, 
    /* store middlewares, etc */ 
) 

export default store 
+0

我開始分解你的反應,並找出罪魁禍首 - 這是匹配的方式被映射。從'this.props'拉出'{match}'後,我把'routeProps.match.params.name'改成'match.props.name',一切正常。這是一個有點慢的加載,但我認爲可以修復一次我清理一些更多的代碼。還有一個問題 - 在每個單獨的組件上使用'mapStateToProps'通常是最佳實踐,而不是僅僅在主要的'App.jsx'文件中使用它呢? – wildlifehexagon

+0

@wildlifehexagon嘿,那很好聽! 是的,通常認爲使用'mapStateToProps'來檢索每個組件的狀態屬性是最佳實踐,您需要它們。 一個好的試金石測試是:如果你將一個值從一個狀態映射到一個像App這樣的父組件,以便將它傳遞給一個子組件,那麼你應該將該值映射到子組件組件的道具開始。 順便說一句,如果你認爲你的問題有待解決,你可以檢查未來的訪客接受的答案嗎? –

+0

明白了。謝謝你的幫助。 – wildlifehexagon

1

你能請嘗試移動withRouter呼叫Routes.jsx

export default withRouter(connect()(Routes)) 

我認爲,需要在同一文件中的任何<Route ... />組件。

+0

這是正確的。如果您沒有用'withRouter'封裝包含''組件的組件,那麼您的組件不會更新路由更改。 –

+0

試過了,但現在我得到'不能讀屬性'params'的未定義錯誤。我正在傳遞'match'對象,所以不確定是什麼導致了這個問題? – wildlifehexagon

+0

我也嘗試在App.jsx中添加我的整個''語句中的路由,但這只是讓我回到了最初的問題,即'page'和'content'未定義。 – wildlifehexagon