React Router V4 未传递 OwnProps
我正在将应用程序从 React Router V2 重构到 V4,并且遇到了一个问题,即
mapStateToProps
中的属性未传递给每个组件。这是我的设置:
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 开发工具时,它显示
page
和
content
未定义。重构时,我在 InfoPage 组件上唯一更改的是添加
match.params
而不是
params
。这让我相信我的 Redux/Router 集成存在问题,特别是
ownProps/routeProps
未正确传递。
您知道这里出了什么问题吗?
首先,确保您正在包装
Routes.jsx
(正如 @lemarc 和 @Kyle Richardson 之前提到的),以便您的路由组件能够正确更新。
当您使用
withRouter
包装连接的组件时,它将使
match
在该组件的
props
中可用。
您不必尝试通过
ownProps
映射
match
,而是可以从包装的组件的
props
中访问它。
此外,您似乎正尝试从子组件
InfoPageView
引用绑定到您的
App
组件的动作创建者。这是 React + Redux 应用中的一种反模式。
如果您的
InfoPageView
需要分派 Action 的能力,则应通过其自己的
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)
)
如果在完成所有这些操作后,您发现
page
和
content
仍然
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
您可以尝试将
withRouter
调用移至 Routes.jsx
export default withRouter(connect()(Routes))
我相信它需要与任何
<Route ... />
组件位于同一文件中。