开发者问题收集

React Router V4 未传递 OwnProps

2017-11-17
1867

我正在将应用程序从 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 开发工具时,它显示 pagecontent 未定义。重构时,我在 InfoPage 组件上唯一更改的是添加 match.params 而不是 params 。这让我相信我的 Redux/Router 集成存在问题,特别是 ownProps/routeProps 未正确传递。

您知道这里出了什么问题吗?

2个回答

首先,确保您正在包装 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)
)

如果在完成所有这些操作后,您发现 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

...同时验证您是否通过 combineReducerspage 减速器传递到您的商店:

import pageReducer from '../reducers/page'

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

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

export default store
Zac Collier
2017-11-18

您可以尝试将 withRouter 调用移至 Routes.jsx

export default withRouter(connect()(Routes))

我相信它需要与任何 <Route ... /> 组件位于同一文件中。

lemarc
2017-11-18