riverpod-containers について
Riverpod の ProviderContainer と ProviderScope で、Flutter アプリ、Dart コード、テストの状態を管理する方法を説明するスキルです。状態の分離、設定、スコープ付きオーバーライドを扱います。
主な機能
- 01Flutter での ProviderScope 設定
- 02Dart での ProviderContainer 利用
- 03テスト用コンテナの作成
- 04オーバーライドとオブザーバーの設定
- 05Provider スコープの解説
活用シーン
- 01Flutter アプリでの Riverpod 状態設定
- 02コマンドラインやサーバー側 Dart での Provider 管理
- 03テストごとの状態分離
- 04サブツリーへの Provider オーバーライド適用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ serverpod/ skills-registry --skill riverpod-containersインストール後、Claude Code で/riverpod-containersを入力して読み込まれたか確認します。
詳細
Riverpod — コンテナー/スコープ
手順
プロバイダー自体は状態を保持しません。状態はProviderContainerに保存されます。Flutter ではProviderScopeウィジェットを使います。このウィジェットはコンテナーを作成し、ウィジェットツリーに公開します。
Flutter:ProviderScope
ウィジェットがプロバイダーを読み取れるよう、アプリのルートをラップします。
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
その後、Consumer/ConsumerWidget/ConsumerStatefulWidget を使って ref を取得し、ref.watch/ref.read を呼び出します。ProviderScope に overrides や observers を渡すこともできます。
Pure Dart:ProviderContainer
コマンドラインまたはサーバーサイドの Dart では、コンテナーを作成して使用し、その後破棄します。
void main() {
final container = ProviderContainer();
try {
final sub = container.listen(counterProvider, (previous, next) {
print('Counter changed from $previous to $next');
});
print('Counter starts at ${sub.read()}');
} finally {
container.dispose();
}
}
状態がコンテナーに保存される理由
- 関心の分離 — 状態を変更できるのはプロバイダー(および ref)のみです。UI は通常、notifier のメソッドを呼び出します。
- テスト — 各テストで新しいコンテナー(例:
ProviderContainer.test())を作成して、初期状態からテストできます。共有のグローバル状態はありません。 - 設定 — オーバーライドとオブザーバーはコンテナー/スコープに設定します。riverpod-overrides と riverpod-observers を参照してください。
- スコープ設定 — 同じプロバイダーでも、ツリー内の異なる部分では異なる状態に解決できます(上級者向け)。riverpod-scoping を参照してください。
テスト
テストで ProviderContainer() を直接使用しないでください。テスト終了時にコンテナーが破棄されるよう、**ProviderContainer.test()**を使用します。
test('Counter starts at 0 and can be incremented', () {
final container = ProviderContainer.test();
expect(container.read(counterProvider), 0);
container.read(counterProvider.notifier).increment();
expect(container.read(counterProvider), 1);
});
ウィジェットテストでは、ウィジェットを ProviderScope でラップし、必要に応じて tester.container() を使ってコンテナーを取得します(riverpod-testing を参照してください)。