torikatsu923.dev

サイト内検索

    【Flutter】RivderpodのStateNotifierがoverrideWithProviderできるようになっていた

    RiverpodでScopedProviderを使わなくてもStateNotifierをoverrideできるようになっていました。

    こんにちは、とりかつ(@torikatsu923)です。

    RiverpodでScopedProviderを使わなくてもStateNotifierをoverrideできるようになっていました。 今回はStateNotifierをoverrideする方法について紹介します。

    今までのStateNotifier.family

    以前以下のような記事を書きました。

    【riverpod】画面遷移時にStateNotifierへ値を渡す方法 - torikatsu.dev

    この記事では StateNotifierFamily を用いてStateNotifierの初期値を設定していました。 そして、初期値を設定したStateNotifierをウィジェットツリーから利用するために以下のようなコードを書く必要がありました。

    このコードでやっていることは以下のとおりです。

    1. StateNotifier.family( providerFamily )を定義する (最終的にウィジェットツリーから利用したいStateNotifier)
    2. 初期値を設定したproviderFamilyをprovideするめに利用するScopedProvider( provider )を定義する
    3. ProviderScopeで生成した providerFamily を、 provider をoverrideすることで子ウィジェットから利用可能にする

    provider定義側

    final provider =
        ScopedProvider<StateNotifierProvider<SomeStateNotifier, SomeState>>(
            (ref) => throw Error());
    
    final providerFamily = 
        StateNotifierProvider.family<SomeStateNotifier, SomeState, String>(
            (ref, text) => SomeStateNotifier(text: text));

    なんらかのウィジェット

          // ...
          return ProviderScope(
            overrides: [
              provider
                  .overrideAs((watch) => providerFamily(text)),
            ],

    ところがRiverpod 1.0.0で以下のような変更が入っていました。

    All providers can now be scoped. Breaking: ScopedProvider is removed. To migrate, change ScopedProviders to Providers.

    riverpod | Dart Package

    ScopedProviderが撤廃されて、全てのProviderが overrideWithProvider することが可能になりました。

    これによって上と同じことを以下のコードで実現できるようになりました。

    provider定義側

    final provider = StateNotifierProvider<SomeStateNotifier, SomeState>(
            (ref) => throw Error());
    
    final providerFamily = 
        StateNotifierProvider.family<SomeStateNotifier, SomeState, String>(
            (ref, text) => SomeStateNotifier(text: text));

    なんらかのウィジェット

          // ...
          return ProviderScope(
            overrides: [
              provider.overrideWithProvider(providerFamily("some text")),
            ],

    StateNotifierをoverrideできると嬉しいこと

    Providerをoverrideするためのコードは大きく変化しているようには見えません。

    では、この変更がどういう時に嬉しいのでしょうか。 この変更はWidgetRef経由でStateNotifierを利用する際にとても便利になります。

    従来のScopedProviderを利用する場合は、StateNotifierへアクセスするために以下のようにする必要がありました。

    ref.read(ref.read(provider))

    ScopedProviderによってprovideされるproviderをread する必要があったため ref.read を二重にしています。大したことないように見えますが、実装を進めていくと毎回二重に ref.read をするのは結構面倒でした。

    これがアップデートによって ref.read が一回で済むようになりました。

    ref.read(provider)

    二重に ref.read する手間を省ける上に、StateNotifier.familyを利用してもStateNotifierと同じように利用できる点がとても便利になりました。

    -––