Flutter の 状態管理で Riverpod が公式の推奨には至っていない理由
March 25, 2022
(個人的メモです。)
Riverpod #
Flutter における状態管理方法の選択肢は公式ページにも記載がある。
- List of state management approaches | Flutter
- https://docs.flutter.dev/development/data-and-backend/state-mgmt/options
シンプルに setState を使用する以外では Provider か Riverpod のパッケージを使うのが一般的。
Provider は Remi Rousselet さんが個人的に開発したパッケージだが、やがて公式にも認められ、現在は公式推奨のアプローチになっている。
この作者が Privider の改良版として作ったのが Riverpod になる。改良点は他の記事から引用させていただく。
Riverpod の良いところ
- Flutter に依存しなくなった(Pure Dart)
- Provider が InheritedWidget をラップしたものだった。
- Riverpod は InheritedWidget を使わずゼロから構築した。
- Provider から状態を読み込む際、BuildContext が必要なくなった。
- コンパイル時にエラーを検知できる
- Provider では実行時にしかエラーが検知できなかった。
- よくあったのが、Provider から状態を読み出そうとして、「Provider が見つからない」エラー
- 同じ型の Provider を複数配信できる
- Provider を Private にできる
- Provider を Widget Tree 限定でなく、Model/Domain Logic/Repository どこでも利用できる
- グローバル変数として Provider を宣言できるようになった
- 使われていない Provider の状態を dispose できる
- Computed で、Provider の状態を使って計算した値を状態として持てる。
- 他にも、Family、AutoDisposeProvider などの新機能多数
- Hooks 的な使い方も可能(ゆえに Hooks API との相性がよい)
- Hooks なしでも使える
しかし Riverpod は残念ながら公式推奨の地位を得るには至っていない。(少なくとも本記事作成時点では。)
この理由は2点考えられる。
1点目は Provider が Flutter を拡張する形で状態管理していたのに対し、Riverpod は Flutter とはほぼ独立して状態管理している点。
この仕組みが何かの不都合につながるわけではないが、そもそも Flutter から独立して実装されているものをあえて Flutter 公式が推奨する必要性もないという感じだろう。
2点目は Flutter Hooks の存在。作者は別に Flutter Hooks というパッケージも作っている。これは React Hooks のように処理を差し込むことができるというもの。
Riverpod は Flutter Hooks と合わせて使用することが推奨されている(Riverpod だけで使うことも可能)。
ただし、Flutter 公式としては、この Flutter Hooks を公式にはサポートしないというスタンス。
Flutter Hooks #
Flutter 公式として Hooks の仕組みをサポートするのはどうかとの提案を Remi Rousselet さんがあげた。
Proposal for hooks · Issue #24474 · flutter/flutter
ここでの公式側の意見だが、Hooks の仕組みを実装せずとも Mixins を使えば同様のことがすでに実現できるため、あえて Hooks をサポートする必要性はないのではないかというのが話の中心になっている。
そしてこの件は以下の Issue に引き継がれた。
Widget hooks · Issue #25280 · flutter/flutter
ここでの主題は Hooks の仕組みを導入することで色々な場所で(あるいはパッケージなどの形で他人とも)コードが共有しやすくなるという点。Hooks(=処理)をウィジェットと分離できるというのが Flutter Hooks の実現したいこと。
その他の部分含め、Flutter Hooks が解決したいことは React が Hooks を導入することで解決したかったことと同じである。
(ではなぜ React は Hooks を導入したのか。これについては記述量が多くなったため本記事の末尾に移動した。また React は Mixins を推奨していない。こちらについても末尾で補足しておく。)
結局、最終的に Hooks の仕組みを公式としてサポートすることにはならなかった。
ただし、Flutter Hooks の考え方を強く否定しているわけではなく、その導入にかかる労力とメリットのパフォーマンスだったり、他のタスクとの優先事項などを総合的に考えると、少なくとも今の時点で公式でサポートするつもりはない、という形に見える。
まとめ #
本記事作成時点で GitHub の Trending で Provider よりも Riverpod のほうが上位に来ている。
https://github.com/trending/dart?since=monthly
このようにコミュニティからの Riverpod の評判は非常に良い。
一方で Flutter Hooks に対する公式のスタンスも考慮に入れた方が良い。
そのため最終的な結論としては、Flutter Hooks を使わずに Riverpod だけを使用するのが良い、というのが個人的意見。
補足:React が Hooks の導入で解決したかったこと #
React も元はクラスベースのコンポーネントが中心だったが、それをファンクションベースのコンポーネントを中心とする方針に変えている。これによって解決したかったことは以下で説明されている。
上記の中でも紹介されているが、以下のカンファレンス動画を見るとよくとわかる。
React Today and Tomorrow and 90% Cleaner React With Hooks - YouTube
ちなみにこちらが React に Hooks を導入する提案の Issue だが、流石に長すぎて読めていない。
RFC: React Hooks by sebmarkbage · Pull Request #68 · reactjs/rfcs
補足:React は Mixins を推奨していない #
以下の記事を参照。
Mixins Considered Harmful – React Blog
記事中で述べられている Mixins を利用することの問題点は以下である。
- Mixins introduce implicit dependencies
- Mixins cause name clashes
- Mixins cause snowballing complexity
1. Mixins introduce implicit dependencies #
Mixins はそのコンポーネントに暗黙の依存関係を発生させてしまう。
ある時、コンポーネントの中の一部のコードを親のコンポーネントに移動させることを試みたとする。しかし、そのコードは Mixins しているコードの依存しており、単純に移動させるだけではダメなのかもしれない。だがそのコンポーネントを見ただけではそのことは分からない。そのコンポーネントが多数 Mixins しているとすると、ではその中のどれを確認すれば良いのか?結局あなたはそれらの全てに目を通さなければいけない。そしてまた気づくことになる。その Mixins がさらにまた別の Mixins を利用していることに。
2. Mixins cause name clashes #
FluxListenerMixin が handleChange()
というメソッドを持っており、WindowSizeMixin もまた handleChange()
というメソッドを持っていたとする。あなたはこれらを一緒に使うことはできないし、あなた自身が作成するコンポーネントもまた handleChange()
というメソッドを持つことはできない。
3. Mixins cause snowballing complexity #
Mixins は最初シンプルだが、開発が進むにつれて次第に複雑化していく傾向にある。