例えば、アクセストークンを Redux のストアに保存していて、そのアクセストークンを使って Web API を呼び出したい。 アクセストークンを受け取って Web API を呼び出すアクションおよび ActionCreator は既にあるとする。
Redux のストアで管理しているステートからコンポーネントの Props にアクセストークンを渡すのは、mapStateToProps でやればいい。 Web API を呼び出す ActionCreator を dispatch する部分は、mapDispatchToProps で書きたいところ。 ただ、mapDispatchToProps 内では mapStateToProps で Props にマップした値を取得できない。 気を利かせて、ownProps に渡してくれたらよかったのに。 さて、どうしよう。
救世主は、connect が受け取る 3 番目の引数、mergeProps だった。 mapStateToProps が返したオブジェクトである stateProps、mapDispatchToProps が返したオブジェクトである dispatchProps、 そして ownProps を受け取り、3 つをマージしたオブジェクトを返す。 mergeProps 内なら、mapStateToProps でマップしたアクセストークンが stateProps から取得できるので、 そのアクセストークンを使って Web API を呼び出すアクションが dispatch できる。
こんな感じで。コードは TypeScript。
import React from 'react'; import { Dispatch } from 'redux'; import { connect } from 'react-redux'; import { AppState } from './reducers'; import { callWebApi } from './actions'; interface IndexPageProps { dispatch: Dispatch; token: string; onLoad: () => void; } class IndexPage extends React.Component<IndexPageProps> { componentDidMount() { this.props.onLoad(); } render() { return (/* 本題ではないので省略 */); } } // アクセストークンを Props にマップ function mapStateToProps( state: AppState, ownProps: IndexPageProps ): IndexPageProps { return { ...ownProps, token: state.login.token, }; } // mapStateToProps でマップした値を使うアクションを dispatch する処理は、 // mapDispatchToProps で書かないでおく function mapDispatchToProps( dispatch: Dispatch, ownProps: IndexPageProps ): IndexPageProps { return { ...ownProps, dispatch, }; } function mergeProps( stateProps: IndexPageProps, dispatchProps: IndexPageProps, ownProps: IndexPageProps ): IndexPageProps { return { ...ownProps, ...stateProps, ...dispatchProps, // mapDispatchToProps ではなく mergeProps で実装する onLoad: () => { // mapStateToProps で props にマップしたものは // stateProps から取得できる const token = stateProps.token; // mapDispatchToProps で props にマップしたものは // dispatchProps から取得できる const dispatch = dispatchProps.dispatch; // mapStateToProps でマップしたデータを使って // アクションを dispatch できる dispatch(callWebAPI(token)); }, }; } export default connect( mapStateToProps, mapDispatchToProps, mergeProps )(IndexPage);