Redux Architecture Guidelinesを読んでの所感
Redux Architecture Guidelinesを読んだので、思ったことをメモしておく。
State
Stateの設計
あらかじめ以下のような観点でStateの設計を考えると良い、とされている。
- APIから取得した複数のリソースをどのようにストアすべきか?
- ローディングといった状態をどのように扱うか?
- 成功や失敗といった通知の表示/消去をどのように扱うか?
- 一貫性や予測可能性が感じられるか? 他のメンバーが簡単に扱うことができるか?
- Redux stateの中のデータに簡単にアクセスすることができるか? プロパティを不要にネストしていないか?
- シリアライズ可能か? 簡単にローカルストレージまたはデータベースに保存できるか?
- Redux stateからではなくURLから取得できるプロパティはあるか?
- 重複したデータはあるか?(そういったデータは、本当に必要か?)
……と、考えておくのが良いことはReduxを少しでも触ったことがあれば思うことではあるのだけど、例えばローディングといった状態を扱う際の定石は何か?ということがみんな知りたいことではあると思う。
オブジェクトの入れ子を避ける
こんな感じの入れ子。
{
foo: {
bar: {
baz: {
qux: ...
}
}
}
}
関連するデータを扱っていると起きがち、とのこと。扱いやすくするためにはRedux自体のガイドに載っているように正規化すると良い。normalizrを使うとサクッと正規化できる。
RawデータのみをStateに格納する
Reactアプリで扱うようなデータには、
- APIから取得したデータ、といった一次データ
- それを加工してアプリで使いやすくしているような二次データ
があるけれども、二次データはStateに保持しない方が良いね、という趣旨。経験上二次データをStateに保持するような設計をしたことがないのでピンとこなかった。
ReactのStateよりReduxのStateを優先する
基本的にデータはReduxのStateに保持させるという方針。Reduxを使うなら、大体がそうなると思う。
が、例えば記事一覧に「いいね」ボタンがある場合で、「いいね」を押したときにサーバと通信するので各ボタンにローディングUIを出したいといったケース。これは各Reactコンポーネントでローディング状態を管理しても良いのではないかと思う。一気に複数のボタンをタップすることもあると思うので、Reduxでこれを管理するのは、ちょっとつらい。
Action
payloadを標準化する
Flux Standard Actionの仕様に乗っ取ろう。これは同意。というか大体みんなそうしていると思う。
Action CreatorをComposableにしよう
Action CreatorをPromiseで包んでおく、というのは非同期を扱う上ではやむを得ないと思われ。その一方で、個人的にはAction Creatorはtypeとpayloadを送信することに徹して、実処理はredux-sagaで書くといった層分けをするのが良いんじゃないかなーと思っているけど、これはこれで結構なコード量になる。結局Promiseにするのが一番シンプルなのか……うーん。
Component Architecture
コンテナ&プレゼンテーションコンポーネント
Reduxのガイドに書いてあるこれ。なんとなく書いていると、自然とコンテナコンポーネント的に書くことになる気がする。
中間コンテナを利用する
コンポーネントを管理するコンテナを管理するコンテナが現れるといったような感じ。これも自然にそうなる感がある。
Reduxはシンプルで扱いやすいけど、Storeのデータ設計をしくじると酷い目に合う。定石を探求していきたい。