3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

showModalBottomSheetの中でStateNotifierProviderの変更を受け取る

Last updated at Posted at 2023-06-18

Stateが変更されてもModalBottomSheetが再描画されずハマったので。
状況は↓こんな感じ。
before_resize.gif

ググってもshowModalBottomSheetの中でStatefulBuilderを使ってsetState()してる記事しか見当たらず、Riverpodの旨味を活かせてない感がありました。

対象読者

  • Flutterのソースが読める人
  • Riverpodを使ったことがある人

FlutterやRiverpodの使い方は本記事では説明しないので公式Docsやその他記事を参照してください。:page_facing_up:

結論

  • showModalBottomSheetの中でConsumer Widgetを使う
  • Consumer Widgetのbuilder内でwatchしてその値を参照する

修正後
after_resize.gif

何故こんな事が起きるのか

※推測多め。

修正前のWidget Treeはこんな感じ。

修正前のWidget Tree

下部のCenter配下がModalBottomSheetのツリー。
showModalBottomSheet()(おそらくDialogも?)を実行するとModalBottomSheetのツリーは MyHomePage 配下ではなく、別のツリーとして構築されてしまう。そのためConsumerで定義したProviderにアクセスできず、変更を受け取れない(多分)。

解決策

Consumer Widgetの使い方

ちょいちょい出ているConsumer Widgetは部分再描画するためのウィジェット。

Consumer can be used to listen to providers inside a StatefulWidget or to rebuild as few widgets as possible when a provider updates.

builder プロパティに監視したいProviderと変更時に再描画したいWidgetを書いてあげる。
watchしているState変数を再描画したいWidget内で参照しないと再描画されないので注意!

Consumerの使い方
Consumer(
  builder: (context, ref, child) {
    final xxxState = ref.watch(監視したいProvider);
    return 再描画したいWidget;
  },
);

Consumer WidgetはあくまでWidgetなので、これをshowModalBottomSheetの中に書けばOK。(謎にここで数時間ハマった。。)

showModalBottomSheetの中でConsumerを使う
showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
+    return Consumer(
+      builder: (context, ref, child) {},
+    );
  },
);

修正後のWidget Treeはこんな感じ。
ModalBottomSheetのツリー内にConsumerがあるので変更を受け取って再描画できる。

修正後のWidget Tree

余談

StatelessWidgetはConsumerWidgetに、StatefulWidgetはConsumerStatefulWidgetに書き換えるのが基本だが、Stateが変化するとページ全体が再描画されてしまう&再描画のコストが掛かってしまう。
個人的には全部StatelessWidgetで書いて、Stateの状態を受け取りたいところだけCosumerで囲む方が再描画のコストも低くなるし、StateはRiverpod、UIはStatelessWidgetに分離出来るから設計的に気持ち良く感じる。

サンプルソース

Commit履歴に失敗パターンと成功パターンを打っているので気になる方は是非。

参考情報

最後に

筆者はFlutterもRiverpodも初心者で見様見真似で書いてるので間違いがあったらご指摘お願いします :bow:

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?