LoginSignup
49
39

More than 5 years have passed since last update.

シンプルなreact-reduxのconnectの書き方

Last updated at Posted at 2018-07-01

react-reduxのconnect関数は、いろいろな書き方ができることで知られています。
(参考:ReactとReduxを結ぶパッケージ「react-redux」についてconnectの実装パターンを試す)

その柔軟さゆえ、実際にアプリケーションの中で書く場合にどのパターンを選ぶか悩むことが多いのではないでしょうか。今回は自分の気に入っている書き方を紹介します。

最もシンプルな書き方

import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

export default connect(
  ({users, todos}) => ({users, todos}),
  {
    actionCreatorA,
    actionCreatorB
  }
)(MyComponent)

これだけです。stateを特にいじらずにconnectしたいときはこれで十分です。action creatorsは、rest spread operatorでまるっと渡してしまっても良いです。

reselectとか使うなら

import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'
import { mySelector } from './selectors'

export default connect(
  state => ({
    todos: mySelector(state)
  }),
  {
    actionCreatorA,
    actionCreatorB
  }
)(MyComponent)

reselectを使ったり、stateのconnectの仕方に工夫がいる場合はこのように書きます。

actionCreatorsをactionsでまとめたい時

import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

export default connect(
  ({users, todos}) => ({users, todos}),
  dispatch => ({
    actions: {
      actionCreatorA: () => dispatch(actionCreatorA()),
      actionCreatorB: () => dispatch(actionCreatorB())
    }
  })
)(MyComponent)

よくある書き方と比べると

import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

function mapStateToProps(state) {
  return { 
    users: state.users 
    todos: state.todos
  }
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

やっていることは紹介したシンプルな書き方と同じことですが、かなり冗長に見えます。

解説

キモは、mapStateToProps、mapDispatchToPropsを定義していないところです。特に再利用するものでもないですし、直接書いたほうが読みやすいと思います。

mapSteteToProps

connectの第一引数、即ちmapStateToPropsは、stateを引数に取り、Objectを返すただの関数です。
これは、stateをDestructuringしてアロー関数にしてconnectに直接渡してあげればシンプルに書けるということですね。

mapDispatchToProps

これはややこしいです。そもそも bindActionCreatorsはどこに行ったのでしょうか。
bindActionCreators の役割は、Store#dispatchで関数をラップすることです。簡易的に書くと、以下のようなobjectを返してくれます。

{
  actionCreatorA: () => {
    dispatch(actionCreatorA())
  },
  actionCreatorB: (foo) => {
    dispatch(actionCreatorB(foo))
  }
}

こうすることで、Store#dispatchを書かずに直接呼び出せるということです。

実はconnect関数も同じことをやってくれます。 正確に言うと、connect関数の第2引数は関数かobjectを取ることができて、オブジェクトが渡された場合はbindActionCreatorsと同じように、object内の各関数をdispatchでラップしてくれます。

この特性を利用すると、紹介したような書き方が実現できます。

export default connect(
  state => ({
    todos: mySelector(state)
  }),
  {
    actionCreatorA,  // dipatchでラップされる
    actionCreatorB  // dispatchでラップされる
  }
)(MyComponent)

以上です。
おかしなところがあればご指摘いただければと思いますmm

49
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
39