2017-11-17 165 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