Chapter 11

.familyの使い方

JboyHashimoto
JboyHashimoto
2023.02.26に更新
このチャプターの目次

https://riverpod.dev/docs/concepts/modifiers/family
これを読む前に、プロバイダとその読み方について読むことを検討してください。このパートでは、.familyプロバイダモディファイアについて詳しく説明します。

.family修飾子の目的はただひとつ、外部パラメータに基づいた一意のプロバイダを取得することです。

familyの一般的な使用例としては、以下のようなものがあります。

FutureProviderと.familyを組み合わせて、IDからMessageを取得する。
プロバイダに現在のロケールを渡して、翻訳を処理できるようにする。


使用するユースケース

公式のページだと参考にするのが難しいなと、思い外部からパラーメーターを渡して、.familyの引数のuserIDが指定した、userIDと一致していなかったら、空っぽのユーザー情報を表示するロジックを作ってみました。

ユーザー情報が入ったモデルクラス

import 'package:flutter/cupertino.dart';

// 外部から変更ができない不変のクラスを作る

class User {
  const User({required this.id, required this.name, required this.age});

  final String id;
  final String name;
  final int age;
  // 普遍のクラスは内容を変更できないので、copyWithを使ってコピーして新しいクラスを作成する
  User copyWith({String? id, String? name, int? age}) {
    return User(
        id: id ?? this.id, name: name ?? this.name, age: age ?? this.age);
  }
}

familyでパラーメーターを渡して、ダミーのIDが一致しているデータだけ画面に表示するコード。

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
import 'package:flutter_template/about_family/user_model.dart';

// Providerにfamilyを使ってuserIDをパラメーターとして渡す
final userProvider = Provider.family<User, String>((ref, userID) {
  if (userID == '88') {
    return const User(id: '0X11', name: 'Jboy', age: 33);
  }
  if (userID == '0x22') {
    return const User(id: '0x22', name: 'ego', age: 34);
  }
  return const User(id: 'id', name: 'name', age: 0);
});

final userIDsProvider = Provider<List<String>>((ref) {
  return ['0X11', '0x22'];
});

final usersProvider = Provider((ref) {
  final userIDs = ref.watch(userIDsProvider);
  return [
    for (final userID in userIDs) ref.watch(userProvider(userID)),
  ];
});

class MyWidget extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    final users = ref.watch(usersProvider);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Family'),
      ),
      body: Column(
        children: [
          // Widgetだとfor文はreturnがない
          for (final user in users)
            ListTile(
              title: Text(user.id),
              subtitle: Row(
                children: [
                  Text(user.name),
                  const SizedBox(width: 20),
                  Text(user.age.toString())
                ],
              ),
            ),
        ],
      ),
    );
  }
}

ID一致している場合

ID一致していない場合