🐥

【Riverpod学習】Providerの種類〜StateProviderについて〜

2024/10/13に公開

以下の公式を読みながらStateProviderについて勉強したのでその備忘録です

https://riverpod.dev/docs/providers/state_provider

StateProviderは、Riverpodで簡単な状態の管理を行うためのプロバイダです。例えば、intやbool、Stringなどのシンプルなデータ型を扱う場合に便利で、Notifierクラスを作る必要がないため、手軽に状態を管理できます。

1. StateProviderの概要

StateProviderは、UIから状態を変更できるプロバイダです。特に、シンプルな値の管理に適しています。例えば、ドロップダウンメニューやチェックボックス、ページネーション、数値入力など、シンプルなUI操作に基づいて変わる状態を管理する際に使われます。

  • int: カウンターやページ番号などを管理する。
  • bool: チェックボックスやトグルスイッチなどの状態を管理する。
  • String: テキスト入力フィールドの内容を管理する。
  • enum: 選択項目(例: フィルタータイプ)を管理する。

2. StateProviderの使い方

例: フィルターを管理するドロップダウン
この例では、商品のソート(並べ替え)を行うためのStateProviderを使って、ドロップダウンメニューの状態を管理しています。

1. 商品データとプロバイダの定義

まず、商品(Product)リストを定義し、そのリストを提供するプロバイダを作成します。

class Product {
  Product({required this.name, required this.price});

  final String name;
  final double price;
}

final _products = [
  Product(name: 'iPhone', price: 999),
  Product(name: 'cookie', price: 2),
  Product(name: 'ps5', price: 500),
];

final productsProvider = Provider<List<Product>>((ref) {
  return _products;
});

ここでは、3つの商品(iPhone、cookie、ps5)を持つリストを定義し、それをproductsProviderとして公開しています。

2. StateProviderを使ったフィルターの定義

次に、商品の並べ替えの方法を管理するためのStateProviderを定義します。並べ替えの基準には、名前で並べ替えるか、価格で並べ替えるかを選択できるようにしています。

enum ProductSortType {
  name,
  price,
}

final productSortTypeProvider = StateProvider<ProductSortType>(
  (ref) => ProductSortType.name, // デフォルトは名前でソート
);

3. UIにドロップダウンを追加

次に、UIにドロップダウンを追加して、ユーザーがソート方法を選べるようにします。選択されたソート方法はStateProviderの状態に保存され、UIが自動的に更新されます。

DropdownButton<ProductSortType>(
  // ドロップダウンの値は、StateProviderで管理している状態
  value: ref.watch(productSortTypeProvider),
  // ユーザーが選択した値でStateProviderの状態を更新
  onChanged: (value) =>
      ref.read(productSortTypeProvider.notifier).state = value!,
  items: const [
    DropdownMenuItem(
      value: ProductSortType.name,
      child: Icon(Icons.sort_by_alpha),
    ),
    DropdownMenuItem(
      value: ProductSortType.price,
      child: Icon(Icons.sort),
    ),
  ],
),

ここでは、ref.watchを使って現在のソート状態を取得し、ユーザーが選択した値をref.readを使ってStateProviderに反映させています。
ref.read(productSortTypeProvider.notifier).stateは、productSortTypeProviderの状態を変更できる部分にアクセスしてstateで現在の状態を表しています

4.商品の並べ替えロジックを追加

次に、選択されたソート方法に基づいて商品のリストを並べ替えるロジックを追加します。productsProviderでproductSortTypeProviderを監視し、ソート順が変更されたらリストを再計算します。

final productsProvider = Provider<List<Product>>((ref) {
  final sortType = ref.watch(productSortTypeProvider);
  switch (sortType) {
    case ProductSortType.name:
      return _products.sorted((a, b) => a.name.compareTo(b.name));
    case ProductSortType.price:
      return _products.sorted((a, b) => a.price.compareTo(b.price));
  }
});

このコードでは、選択されたソート方法に基づいて、商品リストを名前順または価格順に並べ替えます。

3. StateProviderの使いどころ

状態が単純で、UIに対するアクションが少ない場合(数値や文字列、ブール値などの基本的なデータ型を使って、シンプルに状態を管理する場合)には、StateProviderが最適です。
また、カウンターアプリやフォーム入力フィールドの値など、ユーザーが操作するシンプルな状態変更には非常に便利です。

4. StateProviderの限界

複雑なビジネスロジックや状態管理が必要な場合には不向きです。
複雑な状態管理や、状態に対するビジネスロジックが必要な場合にはStateProviderは適していません。代わりに、NotifierProviderを使用して、状態管理とビジネスロジックを分離する方が良いです。

5. まとめ

StateProviderは、シンプルな状態を管理するためのプロバイダで、主に数値や文字列、ブール値の状態をUIと連携して簡単に変更する場面で使います。
シンプルな状態の変更には最適ですが、複雑な状態管理やビジネスロジックが必要な場合にはNotifierProviderを使う方が適しています。
カウンターアプリやフォームフィールドの値管理など、非常に単純な操作にはStateProviderが最適です。

Discussion