simple-web-system technology

Webに関する技術をシンプルに扱うブログ

RiverpodでStateNotifierProviderを使うときは、0.14系からの記事を参照しましょう

FlutterのState管理の定番になりつつあるRiverpodですが、0.14系からStateNotifierProviderの呼び出し方が変わったのはご存知でしょうか。

0.14がリリースされたのは2021/04/04なのですが、検索してみると0.13系までの情報がかなり多かったので、整理してみました。

公式の移行案内

基本的には公式に0.13から0.14への移行案内が書いてあるので、こちらを参照しましょう

beforeとafterを読めばわかるはずです。

https://riverpod.dev/docs/migration/0.13.0_to_0.14.0/

新規の方向けへ

これからRiverpodでStateNotifierを使ってみる方だと、公式の移行の解説だけだとわかりにくいかもしれないので、サンプルコードを用意しました。 コピペして色々いじってみるといいかもしれません。

  1. providerの初期化
  2. StateNotifierからstateの値を取得して、Widgetで表示する。
  3. StateNotifier内のメソッドを呼び出す。

1, 2, 3の順に理解していくとわかりやすいはずです。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

/// intがstateの型
class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() {
    this.state = this.state + 1;
  }
}

/// 1. providerの初期化
/// StateNotifierProviderに<StateNotifier, stateの型>になるように型引数を渡す。0.13系までは型の指定が不要だった。
final counterProvider =
    StateNotifierProvider<Counter, int>((refs) => Counter());

class ExampleScreen extends HookWidget {
  @override
  Widget build(BuildContext context) {
    /// 2. StateNotifierからstateの値を取得して、Widgetで表示する。
    /// StateNotifierからstateの値を取り出す時は、providerをそのまま指定する。0.13系まではprovider.stateだった。
    ///
    /// 値が変更されたら再描画されるように、HookWidget + useProviderを使う。
    final count = useProvider(counterProvider);

    return Scaffold(
      body: Center(
        child: Text(
          count.toString(),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => handlePress(context),
      ),
    );
  }

  void handlePress(BuildContext context) {
    /// 3. StateNotifier内のメソッドを呼び出す。
    /// StateNotifierの取得は、provider.notifierを指定する。0.13系まではproviderだけだった。
    ///
    /// メソッド呼びだしは、context.readでStateNofierを取得して呼び出すと楽
    /// useProviderやwatchはbuild直下じゃないと使いづらい
    /// (それ以外にもレンダリングとか色々理由あるけど)
    context.read(counterProvider.notifier).increment();
  }
}