基本的にはstateはコンポネントに閉じ込められて使うべきで外に影響が染み出していくのはよくない。なので、useStateでシンプルに使うだけなのが一番良い。hooksがあるのでいろんなことがとてもシンプルにできるようになった。 とはいえ、遠いコンポネントと連携させたいケースや、認証状態のようなグローバルで共有したいというものがあるケースも理解できる。あとはキャッシュとか。
新しく入った開発プロジェクトでReactを使っているので、そういう時にどういう選択肢があるのかを整理してみた。
React使うのは3年ぶりくらい。前に使ったときはflux-utils, flow, immutable.jsとかで満足していた。今回のも、なるべく長期で育てていきたいプロジェクト。
今回の結論
頻繁に更新される情報やキャッシュしたいものはRedux ToolKitで書いたReduxで管理して、システムグローバルな参照しかしない情報はContextの利用という合わせ技がいいかなと思っている。
候補
- グローバルな状態を使わない
- 多くの階層を経由してpropsを渡すのを避けたいだけならコンポネントコンポジションを使えばいい [ コンテクスト – React]
- websocketとかで更新情報を配布するようにしておいてメッセージを受けたらAPIからデータ取得するようにすれば、コンポネントを跨いだ更新、参照は不要になる
- Pros.
- すでにsocket使っているなら一方向の循環があると言えるので要素を増やさないで済む
- Cons.
- 認証状態の共有とかではそうもいかないので別途の方法が必要
- キャッシュとかは別途考えが必要
- socketサーバがいないと動かないので準備が増える
- built-inのContextを使う
- Pros.
- Reactにbuilt-inな機能なので追加モジュール不要、メンテナンスも安心
- シンプルなので挙動が想像しやすい
- Cons.
- reducer的な高レベルのファンクションを提供できない
- useReducerで取得できるstate, dispatchを丸ごとContextに突っ込むというやり方もできるけど
- カジュアルに更新するものをContextに入れるのは設計、パフォーマンスの両面でしんどい
- reducer的な高レベルのファンクションを提供できない
- Pros.
- Contextの薄いラッパーでFlux風
- mizchiのちょっとしたスニペット [React Context を用いた簡易 Flux - mizdev]
- Pros.
- contextをちょっと使いやすくする薄いラッパーなので見通しがいいし自前でメンテナンスもできる
- 参照、更新がやりやすい
- Cons.
- 普通にContext使うだけでもいいかもしれない。好みの問題
- Redux Toolkit(RTK)
- [Redux Toolkit | Redux Toolkit]
- Reduxの使いやすくしたツールキット。vanillaなReduxはほとんどのケースで触らなくていいんじゃないか
- createSlice, createAsyncThunkでかなり幸せになれる
- Pros.
- Reduxの実績はたくさん
- UIと状態を切り離せるので、キャッシュとして利用することもできる
- 型付けがこなれているのでdispatchするにしても
dispatch(actions.fetch())
のように文字列を使わずに実行できる
- Cons.
- reactn
- [GitHub - CharlesStover/reactn: React, but with built-in global state management.]
- Pros.
[ global, setGlobal ] = useGlobal()
とするだけでGlobalStateが使えるようになる
- Cons.
- useGlobalだけで済むのは魔法でもなんでもなく、通常の
react
をreactnでラップしてContextを透過させているだけ。ちょっと不安。reactのセキュリティフィックスとかすぐ対応できるの?とか。 - CharlesStoverが一人でメンテ。2018/09から始めていて、今は活発だけど今後のメンテが心配ではある
- useGlobalだけで済むのは魔法でもなんでもなく、通常の
- 余談として、型の適用に面白いアプローチをしているファイルを置いて基本設定を上書きというちょっと黒魔術っぽいやり方
- recoil