🦔

overrideWithValueで上書きした値をモーダルに渡す

2023/12/20に公開

Overview

https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/OverrideWithValueMixin/overrideWithValue.html

公式より引用:

プロバイダーを値でオーバーライドし、デフォルトの動作を排除します。 これにより、自動スコープ メカニズムも無効になります。つまり、オーバーライドされたプロバイダーが依存関係を指定しても、効果はありません。 一般的な使用例としては、サービスを偽の実装に置き換えることによるテスト、または非常に特定の状態に簡単に到達することなどがあります。 プラットフォームまたはその他のパラメータに基づいてクラスの実装を変更することにより、複数の環境に対応します。 この関数は、ProviderScope.overrides または ProviderContainer.overrides と組み合わせて使用する必要があります。

riverpodでテストコードを書くときに、使うことが多いoverrideWithValueですが他のページに値を渡すときに使うこともできるとか?
この場合は、元の値を上書きするんですけどね。


int example(ExampleRef ref, {int? id}) { /* */ }
// ...
exampleProvider.overrideWith(
  (ref) {
    print(ref.id);
  }
)

前回書いた記事で紹介しようとした方法です。果たしてこれでできているのかわからないですが...
https://zenn.dev/joo_hashi/articles/72383283a775cb

summary

前回と同じようにモーダルに渡す値を上書きするだけです。APIからとってきた値を渡すとかの方が、すごいのでしょうけど今回も興味あることをただ追求することだけにしました。

こちらのコードで値を上書きして渡すのをやってみようと思います。前回と違うのは、コンストラクタとfamilyを使わないパターンですね。

サンプル
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final testProvider = Provider((ref) => '上書きする前の値');

class OverRideWithExample extends ConsumerWidget {
  const OverRideWithExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final testValue = ref.watch(testProvider);
    return Scaffold(
      appBar: AppBar(
        title: Text(testValue),
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
                onPressed: () {
                  showModalBottomSheet(
                    context: context,
                    builder: (context) {
                      return ProviderScope(
                        overrides: [
                          testProvider.overrideWithValue('値を上書きした😃 '),
                        ],
                        child: const _Modal(),
                      );
                    },
                  );
                },
                child: const Text('モーダルを表示'))
          ],
        ),
      ),
    );
  }
}

class _Modal extends ConsumerWidget {
  const _Modal({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final idParameter = ref.watch(testProvider);
    return Center(
      child: Text('モーダルに渡された値: $idParameter',
          style: const TextStyle(fontSize: 30)),
    );
  }
}

実行結果:

riverpod generatorを使った場合も同じように使えます。ただ上書きするだけ:

ジェネレータ
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'override_generator.g.dart';


String testValue(TestValueRef ref) {
  return '上書きする前の値';
}

class OverrideGenerator extends ConsumerWidget {
  const OverrideGenerator({super.key});

  
  Widget build(BuildContext context, WidgetRef ref) {
    final testGenerateValue = ref.watch(testValueProvider);
    return Scaffold(
      appBar: AppBar(
        title: Text(testGenerateValue),
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
                onPressed: () {
                  showModalBottomSheet(
                    context: context,
                    builder: (context) {
                      return ProviderScope(
                        overrides: [
                          testValueProvider.overrideWithValue('generatorの値を上書きした💡 '),
                        ],
                        child: const _Modal(),
                      );
                    },
                  );
                },
                child: const Text('モーダルを表示'))
          ],
        ),
      ),
    );
  }
}

class _Modal extends ConsumerWidget {
  const _Modal({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final idParameter = ref.watch(testValueProvider);
    return Center(
      child: Text('モーダルに渡された値: $idParameter',
          style: const TextStyle(fontSize: 30)),
    );
  }
}

実行するときはこちらのコードでimportする。

import 'package:family_app/view/override_generator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const OverrideGenerator(),
    );
  }
}


thoughts

今回は、前回の記事で紹介できなかった他の方法で値を別のページやモーダルに渡す方法をご紹介いたしました。これでいいのかまだ大丈夫かな〜って感じですが😅

Discussion