react + reduxでComponentとContainerをどう使い分けるか?
デバッグ用のツールも導入した!
URLとComponentを一意に関連づけるためにredux-routerも導入した!
さあ、これからが本番です。
ページの構成を作り込んでいくターンだ!!
と意気込んだんですが、早速悩ましい問題が一つ。
Component ? or Container ?
react_on_railsで作成されたプロジェクトには、サンプルアプリがバンドルされるのですが、 そちらの構成が大体このような内容になっています。
HelloWorld アプリのファイル構成
注目したいのは、HelloWorldContainer.jsx と HelloWorld.jsx の二つです。
(react+redux初心者としては、reducerってなんだろ?storeってなんだろ?storeだけなんで単数?とか色々思うところはあるんですが、ひとまずその二つにだけ注目)
client/app/bundles/HelloWorld/containers/HelloWorldContainer.jsx
まずは、Container側から確認します。
今の所「なんのこっちゃ」という感想くらいしか持てません。
connectってなんじゃろ?actionとは?mapStateToPropsとは?えーい、ひとまず先に進んだろ!
client/app/bundles/HelloWorld/components/HelloWorld.jsx
Component側はとても分かりやすくてビックリします。
このシンプルな二つの例を確認しただけで分かること(間違っていても、現段階で持てる認識として)は、、、
Containerとは?
reactとreduxをつなぐためのもの
Componentとは?
reduxが提供するstoreデータ、actionを受け取って動作する、最小構成の部品
(reduxの事を意識しなくてもいい、つまり、connectしない。connectが必要ならそれはContainerとして扱う)
という感じでしょうか?
さて、では、IndexPageというものを用意したい場合、HelloWorldアプリと同様に、
- IndexPage
- IndexPageContainer
を用意するべきでしょうか?
んー、直感的には「NO!」なんですよね。
react + redux初心者なんで、なんの確信もない、ただのイメージですが。
じゃあどうする?
そもそも何が気にくわないのか?
- IndexPage (Component)
- IndexPageContainer (Container)
この構成の何が僕はそんなに気にくわないのでしょうか?理由は色々あります。
冗長すぎないか?
- IndexPage内で利用するComponent群を、IndexPageContainerで意識しないといけない
- IndexPageContainer → IndexPage → IndexPage内の各種Componentまでのデータバケツリレーが発生しそう
IndexPageの再利用性の低さ
- 「Component」って、再利用性が高いイメージ
- IndexPageをComponentって呼びたくない
個人的にはやはり「PageはContainerとして扱いたい!」です。
最終的な構成イメージ
client/app/containers/IndexPage.jsx
client/app/components/InformationList.jsx
うん、この構成でいけると色々いい感じかもしれない!
と、ここで一つ気づくことがあります。
Containerも結局のところComponentじゃん?
うん、どうもそうみたいですね。
connect対象がcomponentだし、componentはcomponentを内包できるし、つまるところ、Containerとは、
「connectされる事になる最上位のComponent」という認識でいいかなと思います。
間違っていたらごめんなさい。
執筆時のシステム構成
サーバーサイド
- ruby: 2.3.3p222
- rails: 5.0.2
- react_on_rails: 6.8.2
クライアントサイド
- react-on-rails: 6.8.2
- react-redux: ^5.0.3
- react-router: ^2.0.0
- redux: ^3.6.0
- redux-router: ^2.1.2
- history: ^2.0.0