😇
whenをネストしたくないから、switch & recordを使った!
🤔やってみたいこと
riverpodを使って、プロバイダーを2個 ref.watch + when
するとデータを2種類 Widget
に渡せるが、 これだとなんかカッコ悪い😅
enum Selected { edit, delete }
class FeedPage extends HookConsumerWidget {
const FeedPage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final selectedMenu = useState<Selected>(Selected.edit);
final tUser = ref.watch(tUserListProvider);
final tTask = ref.watch(tTaskListProvider);
return Scaffold(
appBar: AppBar(),
backgroundColor: AppColor.grey,
floatingActionButton: FloatingActionButton(
backgroundColor: AppColor.navy,
foregroundColor: AppColor.white,
// ボタンを丸くする
shape: const CircleBorder(),
onPressed: () async {
context.goNamed(RouterPath.CREATE_TASK);
},
child: const Icon(Icons.add),
),
body: tUser.when(
data: (tUser) => tTask.when(
data: (tTask) => ListView.builder(
itemCount: min(tUser.length, tTask.length),
itemBuilder: (context, index) {
return Card(
child: Material(
color: const Color(0xFFFFFFFF),
child: ListTile(
onTap: () {
context.goNamed(
RouterPath.FEED_DETAIL,
extra: tTask[index],
);
},
title: Text(tUser[index].job_id),
subtitle: Text(tTask[index].task_name),
trailing: PopupMenuButton<Selected>(
onSelected: (result) {
selectedMenu.value = result;
},
itemBuilder: (context) => <PopupMenuEntry<Selected>>[
PopupMenuItem<Selected>(
value: Selected.edit,
child: const Text('編集'),
onTap: () {
/// TODO: 編集の処理
},
),
PopupMenuItem<Selected>(
value: Selected.delete,
child: const Text('削除'),
onTap: () {
/// TODO: 削除の処理
},
),
],
),
),
),
);
},
),
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error: $error'),
),
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error: $error'),
),
なんとかならないのか....
ネストするのやめたい😅
🚀やってみたこと
Dart3.0から登場した Records
を使うと実現できるらしい???
SwiftのTuple
みたいに、複数の戻り値を返すことができます。
こんな感じでね
多分、recordだろう?
// Dart imports:
import 'dart:math';
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
// Package imports:
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
// Project imports:
import '../../core/theme/app_color.dart';
import '../../infrastructure/supabase_provider/t_task_provider.dart';
import '../../infrastructure/supabase_provider/t_user_provider.dart';
import '../router/router_path.dart';
enum Selected { edit, delete }
class FeedPage extends HookConsumerWidget {
const FeedPage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final selectedMenu = useState<Selected>(Selected.edit);
final tUser = ref.watch(tUserListProvider);
final tTask = ref.watch(tTaskListProvider);
return Scaffold(
appBar: AppBar(),
backgroundColor: AppColor.grey,
floatingActionButton: FloatingActionButton(
backgroundColor: AppColor.navy,
foregroundColor: AppColor.white,
shape: const CircleBorder(),
onPressed: () async {
context.goNamed(RouterPath.CREATE_TASK);
},
child: const Icon(Icons.add),
),
body: switch((tTask, tUser)) {
(AsyncData _, AsyncData _) => ListView.builder(
itemCount: min(tUser.asData!.value.length, tTask.asData!.value.length),
itemBuilder: (context, index) {
return Card(
child: Material(
color: const Color(0xFFFFFFFF),
child: ListTile(
onTap: () {
context.goNamed(
RouterPath.FEED_DETAIL,
extra: tTask.asData!.value[index],
);
},
title: Text(tUser.asData!.value[index].job_id),
subtitle: Text(tTask.asData!.value[index].task_name),
trailing: PopupMenuButton<Selected>(
onSelected: (result) {
selectedMenu.value = result;
},
itemBuilder: (context) => <PopupMenuEntry<Selected>>[
PopupMenuItem<Selected>(
value: Selected.edit,
child: const Text('編集'),
onTap: () {
},
),
PopupMenuItem<Selected>(
value: Selected.delete,
child: const Text('削除'),
onTap: () {
},
),
],
),
),
),);
},
),
(AsyncLoading _, AsyncLoading _) => const CircularProgressIndicator(),
(AsyncError _, AsyncError _) => const Text('Error'),
(_, _) => const Text('No Data'),
},
);
}
}
Riverpodのref.watchで、2つのプロバイダーを監視する。これをrecord
に引数が2個いるので、渡す。
(AsyncData _, AsyncData _)
_を2個つけろと警告が出てきたのでつけたらいけた🙌
コードが変化もしれないが、これしか思いつかなかった😅
body: switch((tTask, tUser)) {
(AsyncData _, AsyncData _) => ListView.builder(
AsyncLoading
とAsyncError
にも_を2個つけろと警告が出てきたのでつけたらいけた🙌
((AsyncLoading _, AsyncLoading _) => const CircularProgressIndicator(),
(AsyncError _, AsyncError _) => const Text('Error'), _, AsyncLoading _) => const CircularProgressIndicator(),
(AsyncError _, AsyncError _) => const Text('Error'),
🙂最後に
結構頑張りました😅
以前やってもなぜできなかったのか....
Discussion