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

となりそう。

まとめ

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

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

と言えそうです。

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