NotifierProvider
NotifierProvider replaces StateNotifierProvider in the newer Riverpod versions, managing complex class-based state synchronously.
A Notifier handles state logic synchronously. It's the recommended alternative to StateNotifier because it removes boilerplate, supports code generation out of the box, and provides direct access to ref.
When to Use Notifier
- Managing complex, synchronous class-based state (e.g., a shopping cart or form inputs)
- Replacing StateProvider with more constrained business logic
- Encapsulating repetitive state manipulation methods
Basic Syntax
Define a Notifier and map its logic using the Riverpod Generator:
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'cart.g.dart';
@riverpod
class Cart extends _$Cart {
@override
List<Product> build() {
// Initial state is an empty cart
return [];
}
void addProduct(Product product) {
// State is immutable, so we create a new list
state = [...state, product];
}
void removeProduct(String productId) {
state = state.where((p) => p.id != productId).toList();
}
}Using Notifier in Widgets
To access the Notifier methods, use ref.read(provider.notifier):
class ShoppingCart extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final cart = ref.watch(cartProvider);
return ListView.builder(
itemCount: cart.length,
itemBuilder: (context, index) {
final product = cart[index];
return ListTile(
title: Text(product.name),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => ref.read(cartProvider.notifier).removeProduct(product.id),
),
);
},
);
}
}⚠️ Important Rule
States in Riverpod are meant to be immutable. Never mutate an object or list directly (e.g., state.add(item)). Always assign a fresh object/collection (e.g., state = [...state, item]).