# Flutter Riverpod State Management

> Reactive state management using Riverpod 2.0 with code generation. Use when managing state with Riverpod providers or using riverpod_generator in Flutter. (triggers: **_provider.dart, **_notifier.dart, riverpod, ProviderScope, ConsumerWidget, Notifier, AsyncValue, ref.watch, @riverpod)

- Skill: `comeonoliver/flutter-riverpod-state-management` (Agent Skill)
- Install (CLI): `npx skillmds@latest add comeonoliver/flutter-riverpod-state-management`
- Raw SKILL.md: https://api.skillmd.com/api/skills/comeonoliver/flutter-riverpod-state-management/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: ComeOnOliver (https://skillmd.com/u/comeonoliver)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/comeonoliver/flutter-riverpod-state-management

---


# Riverpod State Management

## **Priority: P0 (CRITICAL)**

Type-safe, compile-time safe reactive state management using `riverpod` and `riverpod_generator`.

## Structure

```text
lib/
├── providers/ # Global providers and services
└── features/user/
    ├── providers/ # Feature-specific providers
    └── models/    # @freezed domain models
```

## Implementation Guidelines

- **Generator First**: Use **@riverpod** annotations and `riverpod_generator`. Avoid manual `Provider` definitions.
- **Immutability**: Maintain immutable states. Use `Freezed` for all state models.
- **Provider Methods**:
  - `ref.watch()`: Use inside `build()` to rebuild on changes. (e.g., `ref.watch(productsProvider)`)
  - **Side-Effects**: Use **ref.listen()** inside `build()` for navigation/dialogs (e.g., `ref.listen(cartProvider, (prev, next) { ... })` in `ConsumerWidget`). **Never perform side-effects inside provider initialization.**
  - `ref.read()`: Use ONLY in callbacks (`onPressed`).
- **Asynchronous Data**: Use **AsyncNotifier** for complex async logic. The `build()` method calls the repository (e.g., `repository.getProducts()`). Access data via **.when(data: , loading: , error: )** or `AsyncValue` pattern-matching.
- **Architecture**: Enforce 3-layer separation (Data, Domain, Presentation).
- **Testing**: Override providers in widget tests using **ProviderScope(overrides: [provider.overrideWithValue(Mock())])** in `pumpWidget`.
- **Linting**: Enable **riverpod_lint** and `custom_lint` for dependency cycle detection and to catch missing overrides.

## Anti-Patterns

- **Building Inside Providers**: Don't perform side-effects inside provider initialization.
- **Context Access**: Never pass `BuildContext` into a Notifier/Provider.
- **Dynamic Providers**: Avoid local provider instantiation; keep them global.

## Related Topics

layer-based-clean-architecture | dependency-injection | testing


