react、redux環境でのPresentational Components、Container Componentsについて

ReactReduxを勉強しています。 それぞれのチュートリアルをこなしてみたのですが、ReactとReduxをあわせて使う際のコンポーネントの設計方針が今ひとつ腹落ちしません。その原因は、Reduxのドキュメントにある、

  • Presentational Components
  • Container Components

が理解できていないからのように思い、これらについてあらためてドキュメントを読んでみたので、まとめて置こうと思います。
(僕のように英語の苦手な人の役に立つかもしれないと思いつつ...)


まず、Reduxのドキュメント「Usage with React」で、

but if you're unfamiliar, we recommend that you also read Dan Abramov's original article describing the concept of presentational and container components

とあるので、このページを読んでみました。

この記事の中では、

  • Presentational Components、Container Componentsに分割することによるメリット
  • それぞれの性質

などが書かれています。

それぞれの性質については、次のように書かれています。(僕の意訳です...)

Presentational Components

  • 見た目に関心がある。
  • 内部にpresentationalとcontainerの両方のコンポーネントを含むかもしれない。
  • 通常、自身のDOMマークアップとスタイルを持っている。
  • this.props.childrenを介して封じ込めを許可されることがよくある。
  • Fluxアクションやストアなどのアプリの他の部分に依存しない。
  • データのロード方法や変換方法を指定しない。
  • コンポーネントはデータとコールバックをprops経由でのみ受け取る。
  • 独自の状態を持つことはめったにない(そうした場合、データではなくUIの状態である)。
  • 状態、ライフサイクルフック、またはパフォーマンスの最適化が必要なければ、functional componentとして書かれる。

Container Components

  • 仕組みに関心がある。
  • 内部にpresentationalとcontainerの両方のコンポーネントを含むかもしれない。
  • 通常、一部のラッピング用DIVを除くDOMマークアップは持たないし、スタイルも決して持たない。
  • presentationalまたは他のcontainerコンポーネントにデータと振る舞いを提供する。
  • Fluxアクションを呼び出して、presentationalコンポーネントへのコールバックとしてこれらを提供する。
  • データソースとして機能する傾向があるため、多くの場合ステートフルである。
  • 手書きではなく、通常、React Reduxのconnect()、RelayのcreateContainer()、Flux UtilsのContainer.create()などの高次コンポーネントを使用して生成される。

両者の違い

前述のReduxのドキュメントに、両者の違いが纏まっています。
日本語にすると、

Presentational Components Container Components
目的 見え方(マークアップ、スタイル) 仕組み(データのフェッチ、状態の更新)
Reduxを知っているか いいえ はい
データの読み方 propsから読む Redux stateを購読する
データの変更の仕方 propsのコールバックを実行する Redux actionsをディスパッチする
何で書かれるか 手で書かれる 通常、React Reduxで生成される

となりそう。

まとめ

すごくざっくりまとめてしまうと、

  • Presentational Componentsは、Reduxは気にせず、見た目を意識する。
  • Container Componentsは、見た目を気にせず、Reduxを意識する。

と言えそうです。

これを踏まえて、React/Redux約三年間書き続けたので知見を共有します|Enigmo Life などを読みながら、更に勉強してみようと思います。