Pass arguments to a Notifier through its constructor
A basket needs one quantity per product, and the method that changes it needs to know which product it is working on. In Riverpod 3 you give the notifier a constructor parameter and store it in a field:
final quantityProvider =
NotifierProvider.family<Quantity, int, String>(
Quantity.new,
);
class Quantity extends Notifier<int> {
Quantity(this.sku);
final String sku;
@override
int build() => 1;
void increment() {
final max = ref.read(stockApiProvider).inStock(sku);
if (state < max) state++;
}
}- <Notifier, state, argument>
- the argument goes to the constructor
- every method can use the argument
NotifierProvider.family calls the function you give it with the argument. Quantity.new is a constructor tear-off, so the argument lands in sku. From then on, build and every method can read it without passing it around.
Callers pick the instance by calling the provider with an argument:
void addOneLamp(WidgetRef ref) {
ref.read(quantityProvider('lamp').notifier).increment();
}What changed from Riverpod 2
Riverpod 2 had a separate FamilyNotifier class. The argument came in through build(String sku) and methods read it back from a getter called arg. That class is gone:
class OldQuantity extends FamilyNotifier<int, String> {
@override
int build(String sku) => 1;
void increment() {
// `arg` held the argument.
if (arg.isNotEmpty) state++;
}
}To migrate, extend Notifier, move the build parameter into the constructor, and rename arg to your field. The same goes for AsyncNotifier and StreamNotifier. There are no family variants of those either.
Good to know
- One instance per argument.
quantityProvider('lamp')returns the same notifier every time you call it with'lamp', and'rug'gets its own. - Arguments are compared with
==. Strings, numbers, enums and records work out of the box. For your own classes, implement==andhashCode, or every call creates a new provider. - Need more than one argument? Pass a record, such as
(shop: 'north', sku: 'lamp'). Records already have value equality. - Add
.autoDispose(orisAutoDispose: true) if the per-argument state should go away when no screen shows that product.
Adapted from tip #97 in Flutter Tips & Tricks by Andrea Bizzotto (MIT). Updated for current Flutter. Not affiliated with or endorsed by the original author. Suggest an edit.