react、redux環境でのPresentational Components、Container Componentsについて
ReactとReduxを勉強しています。 それぞれのチュートリアルをこなしてみたのですが、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 などを読みながら、更に勉強してみようと思います。