React+Reduxの基本的構造の解説


まえがき

こちらの記事の続きになります。

チュートリアルのUsage with Reactの部分です。
ReduxによるState管理をReactから呼び出す方法についてまとめてあります。

Componentの使い分け

React+Redux構成ではReactのComponentを以下の2種類に分けて考えます。

  • Presentational Components
  • Container Components

概念的なものなので、どっちつかずのコンポーネントもあります。

Presentational Component

描画用のコンポーネント。
Reduxと直接関係しない通常のReactのコンポーネントのことです。
Container Componentとの対比として用いられます。

Container Component

Reduxとの接続用コンポーネントです。
描画を直接行わず、内包したコンポーネントの内容をそのまま表示します。
生成用の関数が用意されていて、通常はそれを使って生成します。

どっちつかず

描画もするReduxへのアクセスも行うコンポーネントです。
小規模なら問題ないですが、太ってきたら上記の2つのコンポーネントに分離を検討します。

Container Componentの仕様

Container Componentはコンポーネントを1つだけ内包します。
初期化の際に以下の振る舞いをします。

  • Stateの一部をpropsに読み込む
  • dispatchを呼ぶためのmethodpropsにセットする
  • 拡張したpropsで内包したコンポーネントを初期化する

またStateに変更があった場合、propsに変更があった場合に子要素の再初期化をします。
結構高機能ながらもパターン化されているため、専用の生成関数を使って生成します。

react-reduxパッケージ

Container Componentを生成するためのパッケージです。
以下の2つが入っています。

  • Providerコンポーネント
  • connect関数

Prodiverコンポーネント

Container ComponentがアクセスするStoreをセットするためのコンポーネントです。
後述のconnect関数で生成されるContainer ComponentProviderコンポーネント配下でしか機能しません。

ほぼ固定の呪文でトップレベルに一つだけ宣言します。

import { Provider } from 'react-redux'
...
const NyaaanComponent = (props) => ( 
  <Provider store={store_you_created}>
    <YoureContainerComponent />
    ...
  </Provider>
)

connect関数

以下の2つのパラメータを使用してReduxとのコネクションを作ります。

  • mapStateToProps
  • mapDispatchToProps
const connection = connect(
  mapStateToProps,
  mapDispatchToProps
)

このコネクションに内包するコンポーネントをセットしてContainer Conponentを作成します。

const MyContainerComponent = connection(InternalComponent)

コネクションは使い捨てなのでこんな合わせてこう書きます。

const MyContainerComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(InternalComponent)

mapStateToProps

Stateを元にpropsの拡張する処理を書きます。
Container Component自体のpropsも渡ってくるので細かな振る舞いが実装できます。
あくまでmapperなのであまり複雑な処理を入れないほうが無難でしょう。

const mapStateToProps = (state, ownProps) => {
  return {
    user: state.user,
  }
}

内包されたコンポーネントは他のpropsメンバと同様にアクセスできます。

const InternalComponent = (props) => (
  <h1>My name is {props.user}<h1>
)

mapDispatchToProps

dispatchを呼び出すmethodを定義してpropsにセットします。

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    addItem: (args) => { dispatch(createAddAction(args)) },
    removeItem: () => { dispatch(createRemoveAction()) },
  }
}

以下のようにmethodを呼び出すことでdispatchが呼び出される仕組みです。

props.addItem('nyaaan')

まとめ

  • Presentational ComponentContainer Componentがある
  • Reduxと関係するのはContainer Component
  • Container ComponentStateの内容とdispatch実行用関数をpropsにセットする