🤿
riverpodのfamilyでモーダルに値を渡す
Overview
riverpodのfamilyを使ったユースケースについて今回ご紹介しようと思います。とはいってもあまり参考にならないかもしれないです💦
なぜ記事を書こうかと思ったかというと、業務で他のページやモーダルに値を渡すときに、family
を使うとのことで試してみました。他にも方法はあります。
summary
今回はモーダルを表示して、そこに値を渡してみましょう!
プロバイダーを使ってグローバルに値を渡すのをやってみようと思います。単純すぎて面白くないと思いますが、紹介している例がないな〜と思って記事を書いてます(^^;;
Listを使った方法も紹介してますが、これは仕事で似たようなことをしたのでダミーのデータですが作ってみました。
使用例
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// Userクラス
class User {
final int id = 34;
final String name = 'Jboy';
final String email = 'Jboy@co.com';
}
// idをfamilyでモーダルに渡す
final idProvider = Provider.family<int, int>((ref, id) => id);
// UserクラスをListとfamilyでモーダルに渡す
final userProvider = Provider.family<User, int>((ref, id) {
final user = User();
return user;
});
class FamilyExample extends ConsumerWidget {
const FamilyExample({Key? key}) : super(key: key);
Widget build(BuildContext context, WidgetRef ref) {
// Userを格納したList
final users = <User>[];
// Userを10個作成してListに格納
for (var i = 0; i < 5; i++) {
users.add(User());
}
return Scaffold(
appBar: AppBar(
title: const Text('Family Example'),
),
body: Column(
children: [
Center(
child: ElevatedButton(
onPressed: () {
final id = ref.read(idProvider(1));
showModalBottomSheet(
context: context,
builder: (context) {
return _Modal(idParameter: id);
},
);
},
child: const Text('Show Modal'),
),
),
const SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
subtitle: Text(users[index].email),
onTap: () {
// indexのidをモーダルに渡す
final id = ref.read(idProvider(users[index].id));
showModalBottomSheet(
context: context,
builder: (context) {
// indexのidをモーダルに渡す
return _Modal(idParameter: id);
},
);
},
);
},
),
)
],
),
);
}
}
// モーダルのコンポーネント
class _Modal extends ConsumerWidget {
const _Modal({Key? key, required this.idParameter}) : super(key: key);
final int idParameter;
Widget build(BuildContext context, WidgetRef ref) {
final id = ref.watch(idProvider(idParameter));
return Center(
child: Text('モーダルに渡されたID: $id', style: const TextStyle(fontSize: 30)),
);
}
}
// ignore: unused_element
class _UserModal extends ConsumerWidget {
const _UserModal({Key? key, required this.idParameter}) : super(key: key);
final int idParameter;
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProvider(idParameter));
return Center(
child: Column(
children: [
Text('モーダルに渡されたID: ${user.id}', style: const TextStyle(fontSize: 30)),
Text('モーダルに渡されたUser: ${user.name}',
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 'family_generator.g.dart';
int idValue(IdValueRef ref, int id) {
return id;
}
class FamilyGenerator extends ConsumerWidget {
const FamilyGenerator({super.key});
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Family Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
final id = ref.read(idValueProvider(1));
showModalBottomSheet(
context: context,
builder: (context) {
return _Modal(idParameter: id);
},
);
},
child: const Text('Show Modal'),
),
),
);
}
}
// モーダルのコンポーネント
class _Modal extends ConsumerWidget {
const _Modal({Key? key, required this.idParameter}) : super(key: key);
final int idParameter;
Widget build(BuildContext context, WidgetRef ref) {
return Container(
height: 300,
color: Colors.white,
child: Center(
child: Text(
'id: $idParameter',
style: Theme.of(context).textTheme.headline4,
),
),
);
}
}
実行するときは、main.dartはこのように書いてください:
import 'package:family_app/view/family_example.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 FamilyExample(),
);
}
}
thoughts
他にもモーダルや次のページに値を渡す方法はありますが、割と簡単な方のfamilyを使ってみました。でもこれはデメリットもあって、複数のページでプロバイダーを使っているときに、後でfamily追加したら、引数を渡すのが必須になるので、そこが欠点ですね。
他の方法でやっても何かしら、デメリットはあるんですけどね...
Discussion