はじめに
hooks_riverpod
は、Flutterでの状態管理ライブラリRiverpod
とフック機能Flutter Hooks
を組み合わせた強力なパッケージです。hooks_riverpod
を使うことで、状態管理がシンプルになり、状態に応じたUIの更新を直感的に行えるようになります。特に、フックを活用することで、状態の管理やリソースのクリーンアップを簡潔に記述できるため、より効率的にFlutterアプリケーションを開発できます。
この記事では、hooks_riverpod
のセットアップから基本的な使い方、実際の利用例まで詳しく解説します。Flutterの開発経験がある方でも、hooks_riverpod
を使うことで、状態管理がさらに快適になるでしょう。
hooks_riverpodとは
hooks_riverpod
は、Riverpod
の状態管理機能とFlutter Hooks
のフック機能を統合したパッケージです。Flutter Hooks
のコンセプトを取り入れることで、状態管理とUIのロジックをシンプルに記述でき、リソースのクリーンアップなどが簡単になります。
hooks_riverpodの主な特徴
- フックを活用したシンプルな状態管理:状態の管理やUIの更新がより直感的に行える。
- リソースのクリーンアップが簡単:フックによって、不要になったリソースを自動的に解放できる。
- Riverpodのすべての機能に対応:
Riverpod
のプロバイダや依存関係管理をそのまま利用可能。
なぜhooks_riverpodを使うべきか?
- UIロジックを簡潔に記述:状態管理とUIロジックがフックによってシンプルにまとめられます。
- 効率的なリソース管理:ウィジェットのライフサイクルに応じてリソースを自動的にクリーンアップ。
- パフォーマンス向上:不要な再レンダリングを防ぐことで、アプリケーションのパフォーマンスが向上します。
hooks_riverpodのセットアップ
まず、pubspec.yaml
にhooks_riverpod
パッケージを追加します。
dependencies:
flutter:
sdk: flutter
hooks_riverpod: ^2.5.1
次に、依存関係をインストールします。
flutter pub get
hooks_riverpodの基本的な使い方
1. ProviderScopeでアプリを包む
まず、hooks_riverpod
を使用する際は、アプリケーション全体をProviderScope
で包む必要があります。これにより、すべてのプロバイダがアプリ全体で利用できるようになります。
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter/material.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
2. ref.watchを使ったプロバイダの状態監視
hooks_riverpod
の基本的な状態管理は、プロバイダを使って行います。useProvider
は廃止され、代わりにWidgetRef
を使ってref.watch
で状態を監視するのが現在の標準です。
例:シンプルな文字列プロバイダ
final helloWorldProvider = Provider<String>((ref) => 'Hello, World!');
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// WidgetRefを使ってプロバイダの状態を監視
final value = ref.read(helloWorldProvider);
return Scaffold(
appBar: AppBar(title: Text('Riverpod with Hooks')),
body: Center(child: Text(value)),
);
}
}
3. StateProviderを使った状態変更
StateProvider
を使えば、カウンターのような状態を簡単に管理できます。WidgetRef
を使って、ref.watch
やref.read
を活用し、状態の監視や変更を行います。
例:カウンターアプリの実装
final counterProvider = StateProvider<int>((ref) => 0);
class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// カウンターの値を監視
final count = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: Text('Counter Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: $count', style: TextStyle(fontSize: 40)),
SizedBox(height: 20),
ElevatedButton(
// カウンターの値を変更
onPressed: () => ref.read(counterProvider.notifier).state++,
child: Text('Increment'),
),
],
),
),
);
}
}
解説
ref.watch(counterProvider)
:カウンターの現在の値を取得して監視します。状態が変更されるたびにUIがリビルドされます。ref.read(counterProvider.notifier)
:状態を直接操作して変更するために使用します。
非同期処理とFutureProvider
非同期処理を行う場合は、FutureProvider
を使います。以下は、APIなどのデータを非同期で取得する例です。
final dataProvider = FutureProvider<String>((ref) async {
await Future.delayed(Duration(seconds: 2));
return 'Hello from Future!';
});
class HomeScreen extends HookWidget {
@override
Widget build(BuildContext context) {
// 非同期データを監視
final asyncValue = ref.watch(dataProvider);
return Scaffold(
appBar: AppBar(title: Text('FutureProvider Example')),
body: Center(
child: asyncValue.when(
data: (value) => Text(value),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
),
),
);
}
}
解説
FutureProvider
:非同期データを提供するプロバイダで、APIリクエストやデータベース操作などに使われます。asyncValue.when
:非同期処理の状態に応じて、データ表示、ローディングインジケーター、エラーメッセージの表示を切り替えます。
Riverpodのベストプラクティス
- ProviderScopeを適切に使用
- すべてのプロバイダは
ProviderScope
内で管理されるため、これをアプリのルートに配置することで、すべてのプロバイダが適切に管理されます。
- すべてのプロバイダは
ref.watch
とref.read
の使い分けref.watch
:プロバイダの値を監視し、変更があるたびにUIを再レンダリングします。ref.read
:値を一度取得するだけ、または値を更新する場合に使います(再レンダリングは行われません)。
- 非同期データの管理
FutureProvider
やStreamProvider
を使って非同期データの状態(ロード中、エラー、成功)を適切に処理することが、ユーザーフレンドリーなUIを提供する鍵です。
まとめ
hooks_riverpod
を活用することで、Flutterアプリケーションの状態管理が簡単になり、UIロジックがシンプルに記述できます。特に、WidgetRef
を使ったref.watch
による状態管理は直感的で、プロジェクトの複雑度に応じてスケーラブルに使えます。この記事を参考に、hooks_riverpod
をマスターし、Flutter開発をさらに効率的に行いましょう。