react-reduxのmapStateToPropsとmapDispatchToPropsは必要なのか
[追記] 続きです。
アプリエンジニアの原です。
ReactNativeでアプリを作る時はReduxを使っていて、ReduxのStoreとReactのComponentをBindingしてくれるreact-reduxが便利なので使っています。
react-reduxが提供するconnect
というStoreとComponentをBindingする関数が在るのですが、
connect( mapStateToProps, mapDispatchToProps, mergeProps, )(Component)
という感じで、3つの関数を引き数にしています。
mapStateToProps
これはReduxのStoreを第一引き数に取る関数で、ComponentにPropsとして渡すものをフィルタリングしたい時に使います。例えばStoreのUserからnameをPropsとして渡したい場合は
//第一引き数はstore const mapStateToProps = store => ({ name: store.user.name }); connect(mapStateToProps)(Component); //Componentはthis.props.nameでアクセス可能
こんな感じでフィルタリングしてComponentにPropsと渡すことが出来ます。
mapDispatchToProps
これはReduxのDispatchを第一引き数に取る関数で、変更を伝えるアクションを作成する時に使います。例えばボタンが押された時にUserのnameを変更するアクションを作成する場合は
// 第一引き数はReduxのdispatch関数 const mapDispatchToProps = dispatch => ({ updateName: name => dispatch({ type: UPDATE_NAME, name }) }); connect(null, mapDispatchToProps)(Component); //Componentはthis.props.updateName('name')でアクセス可能
こんな感じで作成したアクションをComponentのPropsとして渡すことが出来ます。
mergeProps
これは第一引き数にmapStateToProps、第二引き数にmapDispatchToPropsをとる関数で新しPropsを作成します。 デフォルトでは
Object.assign({}, ownProps, stateProps, dispatchProps)
という処理を行います。
(ownPropsはComponentが持つプロパティです。mapStateToProps, mapDispatchToProps共に第二引き数, mergePropsは第三引き数で受取ることができます)
疑問
結論からいうとmapStateToPropsとmapDispatchToPropsの使い所がわかりません
例えば, Userの情報をサーバーから取得してStoreを更新する処理を考えます。
ユーザーの情報を取得するAPIにはユーザーのトークンが必要なのでStoreから取得する必要があります。
サーバーから取得したレスポンスでStoreを更新するためにDispatch関数が必要です。
なので、mergePropsを使わない場合は
const mapStateToProps = store => ({ token: store.user.token }); const mapDispatchToProps = dispatch => ({ fetchUser: token => fetch(...) } }); connect( mapStateToProps, mapDispatchToProps, )(Component);
のようになり、ComponentがfetchUserにトークンを渡す責務が発生します。
Componentは表示やUIイベントの通知に関わる処理だけをするべきであり、またtoken自体描画には全く関係無いのでPropsとして渡すのは不適切な気がします。
なので、ここでmergePropsを使ってtokenを渡す処理を内包すると
const mapStateToProps = store => ({ token: store.user.token }); const mapDispatchToProps = dispatch => ({ fetchUser: token => fetch(...), //tokenを受け取ってfetchを実行するための関数を返す。 }); const mergeProps = (state, action) => ({ fetchUser: () => action.fetchUser(state.token), }); connect( mapStateToProps, mapDispatchToProps, mergeProps )(Component);
これでも可能ですが、
なんなら
const mapStateToProps = store => store; const mapDispatchToProps = dispatch => ({ dispatch }); const mergeProps = (store, { dispatch }) => ({ fetchUser: () => { const token = store.user.token; fetch(...); } }); connect( mapStateToProps, mapDispatchToProps, mergeProps )(Component);
コレが一番シンプルなのでは??
という結論に今のところ至っており、
mapStateToPropsとmapDispatchToPropsは必要なのか
です。
だれか教えてください。よろしくお願いします!
宣伝
このイベントでReactNativeに関する発表をします。