🐨

【Riverpod学習】ref.watchとref.readとref.listenの使い分け

に公開

Riverpodでプロバイダの状態を操作・監視する際に使われるref.watchとref.readとref.listenについて学習したのでその備忘録です

以下のコードの例にref.watchとref.readとref.listenの使い分けを勉強します。

class TodoListView extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    // プロバイダの状態を監視
    List<Todo> todos = ref.watch(todosProvider);

    return ListView(
      children: [
        for (final todo in todos)
          CheckboxListTile(
            value: todo.completed,
            onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id),
            title: Text(todo.description),
          ),
      ],
    );
  }
}

ref.watch:状態の監視

ref.watchは、プロバイダの状態を監視し、その状態が変化したときにウィジェットを再描画します。これは、プロバイダの状態をUIに反映させる場合に使われます。

主な特徴

リアクティブ:プロバイダが提供するデータが変わるたびに、ref.watchを使ったウィジェットやコードが再実行され、UIが更新されます。
再描画をトリガー:watchを使ったウィジェットは、プロバイダの状態が変わると自動的に再描画されます。

List<Todo> todos = ref.watch(todosProvider);

このコードでは、todosProviderが提供するList<Todo>を監視しています。もしtodosProviderの状態が変わると、このList<Todo>も更新され、関連するウィジェットが再描画されます。

使う場面

プロバイダの状態をUIに表示したい場合。
状態が変わったら、自動的にUIを更新する必要がある場合。

ref.read:状態の取得または操作

ref.readは、プロバイダの状態を一度だけ取得し、その状態を操作するために使います。readを使うと、その状態が変わってもウィジェットの再描画は行われません。

主な特徴

一度だけ取得:readを使う場合、その時点でのプロバイダの状態を取得するだけで、変更があってもその結果には反映されません。
操作に便利:状態を変更する関数(toggleやaddTodoなど)を呼び出す際によく使われます。

onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id)

このコードでは、ref.readを使ってtodosProviderにアクセスし、そのnotifier(Todosクラスのインスタンス)を取得して、toggleメソッドを呼び出しています。これはタスクの完了状態を切り替えるための操作です。

使う場面

プロバイダの状態を使って一度だけ操作したい場合。
ボタンのクリックや入力など、ユーザーのアクションに応じて状態を変更したい場合。

ref.listen

  • ref.listenはプロバイダの状態の変更をリスニングし、変更があったときに特定のコールバックを実行します。
  • ウィジェット全体を再ビルドするのではなく、一度設定したコールバックで必要な処理だけを実行したい場合に使います。
  • このコールバックは値の変化(成功、エラー、ロード中など)に応じて適切に処理を行うために便利

使い分けのポイント

ref.watch

  • データを表示するために使用し、状態の変化に応じてウィジェットを再描画する。
  • リアクティブな動作が必要な場合に使用。

ref.read

  • データの操作や一時的な取得が必要な場合に使用。
  • 再描画をトリガーしたくないときに使用。

ref.listen

  • ウィジェット全体の再ビルドをせずに、プロバイダの状態変化に応じた適切な処理を行いたいとき

watchを使った状態の監視

List<Todo> todos = ref.watch(todosProvider);

ここでは、todosProviderを監視しているため、Todoリストに変更があれば自動的にUIが更新されます。

readを使った状態の変更

onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id)

このonChangedハンドラでは、readを使ってプロバイダの状態を一度だけ取得し、toggleメソッドを呼び出しています。toggleメソッドがタスクの状態を変更しても、ここではウィジェットの再描画はトリガーされません。

まとめ

  • ref.watch: プロバイダの状態を監視し、状態の変化に応じてウィジェットを再描画する。データを表示する際に使用。
  • ref.read: プロバイダの状態を一度だけ取得し、操作を行う。再描画をトリガーせずに状態を変更したい場合に使用。
    使い分けは、UIに反映させたいかどうかがポイントです。

Discussion