Chapter 16

[v0.14.0以下版] context.readでwatchせずにProviderを利用する

村松龍之介
村松龍之介
2023.02.12に更新

Widgetの再構築が不要なときに使う context.read

以下のようにProviderを watch する方法があります。

Widget build(BuildContext context, ScopedReader watch) {
  // StateProvider<int>
  final counter = watch(counterProvider);
  return ElevatedButton(
    onTap: () => counter.state++,
    child: Text('+1'),
  );
}

しかし、例えば以下の状況では、Counterの値を表示していないため watch する必要がありません。
Counterの値が変更された時、無駄にElevatedButton Widgetが再構築されてしまいます。

ここで行いたいのは、ボタンを押したときにCounterの値を変更したいだけです。

そこで context.read を使用して、以下のように書き換えることができます。

Widget build(BuildContext context, ScopedReader watch) {
  return ElevatedButton(
    onTap: () => context.read(counterProvider).state++,
    child: Text('+1'),
  );
}

watch が無くなったので、 Counterの値が変更されてもElevatedButtonが再構築されることがなくなりました👏

StateNotifierでは .notifier でOK

Providerによっては、 context.read を使用せずとも状態を watch せずに取得する方法が用意されています。

StateNotifierでは .notifier を使用します。

final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());


Widget build(BuildContext context, ScopedReader watch) {
  // そのまま `watch` するとStateを取得しますが、 `notifier` を付けることで
  //  `context.read` を使用した時と同じように、再構築されない `Counter (StateNotifier)` が取得できる
  final counter = watch(counterProvider.notifier);

  return RaisedButton(
    // onPressedなどで使うことができる
    onPressed: counter.increase,
    child: Text('+1'),
  );
}

buildメソッド内では使用しないようにする

参考リンク

context.read(myProvider) | Riverpod
https://riverpod.dev/docs/concepts/reading#myproviderreadbuildcontext