Flutter ModalBottomSheetを閉じたときに実行した処理ではriverpodの状態が更新されていなかった

# はじめに

https://api.flutter.dev/flutter/material/showModalBottomSheet.html

👆のModalBottomSheetを閉じた時に特定の処理を実行する方法として、例えば以下のようなやり方があります。

```dart
            showModalBottomSheet(
              context: context,
              isScrollControlled: true,
              shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
              ),
              builder: (context) => const BottomSheet(),
            ).whenComplete(() {
               print('ModalBottomSheetが閉じた');
            });
```

`whenComplete`が実行されるときに取得できるriverpodで状態管理してる値が更新されず、次の操作で`whenComplete`が実行された際に反映されるという問題に直面したのです。。。

イメージとしては
①ModalBottomSheetを開いて、その中でriverpodで状態管理してる値Aを変更する
👇
②ModalBottomSheetを閉じる
👇
③`whenComplete`が実行される
👇
④値Aを使って必要なメソッドを実行(しかし値Aは①で変更した値ではなく、その前の値)

よくわからないかもですが、こんな感じですw

ファイルの構成はMVVMっぽい感じで以下の通り
・search_page.dart（view）
・search.dart（model）
・search_view_model.dart（ViewModel）

https://zenn.dev/koji_1009/articles/f15ff24e20e36f





# 環境
hooks_riverpod + freezed + StateNotifierで状態管理をやってます

```yaml
environment:
  sdk: ">=2.16.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  hooks_riverpod: ^2.0.0-dev.0
  freezed_annotation: ^1.1.0

dev_dependencies:
  freezed: ^1.1.1
```





# 状態が更新されていなかった時のコード
まずは思った通りの挙動にならなかった時:poop:

## モデルファイル

```dart:search.dart
@freezed
class Search with _$Search {
  factory Search({
    @Default('') String date,
  }) = _Search;
}
```


## viewファイル

```dart:search_page.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import '../search_provider.dart';

class SearchPage extends HookConsumerWidget {
  const AreaAndCategory({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final search = ref.watch(SearchProvider);
    final date = searchJob.date;

     return Row(
      children: [
        Expanded(
            child: GestureDetector(
          onTap: () {
            showModalBottomSheet(
              context: context,
              isScrollControlled: true,
              shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
              ),
              builder: (context) => const AreaSheet(),
            ).whenComplete(() {
              // ref.watchによって監視されているdateがModalBottomSheetで選択した値によって変わる・・・と思っていた。。
              ref
                  .read(SearchProvider.notifier)
                  .getItems(context: context, date: date);
            });

 }
}
```

## 処理を実行するViewModelファイル
ここの引数で受け取る`date`がModalBottomSheetで変更した値ではなかった。。。

```dart:search_view_model.dart
  Future<void> getItems({
    required BuildContext context,
    String date,
  }) async {
    // 何らかの処理
    print(date);
  }
```



# 状態が更新されていた時のコード
これで思った通りの挙動になりました！！:innocent:

## モデルファイル
ここは変化なし

```dart:search.dart
@freezed
class Search with _$Search {
  factory Search({
    @Default('') String date,
  }) = _Search;
}
```


## viewファイル
**getItemsメソッドに引数で`date`を渡すのをやめました！！**
:dancer_tone5:



```dart:search_page.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import '../search_provider.dart';

class SearchPage extends HookConsumerWidget {
  const AreaAndCategory({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {

     return Row(
      children: [
        Expanded(
            child: GestureDetector(
          onTap: () {
            showModalBottomSheet(
              context: context,
              isScrollControlled: true,
              shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
              ),
              builder: (context) => const AreaSheet(),
            ).whenComplete(() {
              // 引数をcontextだけにした
              ref
                  .read(SearchProvider.notifier)
                  .getItems(context: context);
            });

 }
}
```

## 処理を実行するViewModelファイル
viewから引数で`date`を受け取るのではなく、StateNotifierの`state`から取得に変更

```dart:search_view_model.dart
  Future<void> getItems({
    required BuildContext context,
  }) async {
    // 何らかの処理
    print(state.date);
  }
```

①ModalBottomSheetを開いて、その中でriverpodで状態管理してる値Aを変更する
👇
②ModalBottomSheetを閉じる
👇
③`whenComplete`が実行される
👇
④値Aを使って必要なメソッドを実行(値Aは①で変更した値)

これで上記のような思った挙動になりました！！！

**誰か原因を言語化してください:raised_hands_tone2:**