Search code examples
flutterriverpodflutter-riverpod

Riverpod: Is it wrong to refer in onPressed to a provider obtained earlier by ref.watch?


Riverpod docs say to use ref.read in callbacks like a button's onPressed, since you must not use ref.watch there.

Is it OK to do something like this?

build(context, ref) {
  // Use ref.watch ahead of time, because I refer to p all over 
  // the widget tree. p is a mutable ChangeNotifier
  final p = ref.watch(myProvider);

  return ElevatedButton(
    onPressed: () {
      // Refer to provider obtained via ref.watch earlier
      p.mutateSomehow(),
    },
    child: /* huge tree referring to p 20 times */
  );
}

? I'm doing this all over my code and it seems to work fine, but if this pattern were OK it seems like Riverpod would just recommend it and deprecate ref.read.


Solution

  • let say you have a provider defined like this: final pProvider = StateProvider<int>((ref)=> 0);

    and inside your build, you watch its value like this: final p = ref.watch(pProvider.state).state;

    now, the p inside your build is a stored value of your provider.

    inside your callback, if you want to increment the value of p, you can do so by just saying p++ or p + 1, however, that means that you are just incrementing the fetched value and not the state of the provider itself. this is mostly the scenario when you want to fetch the value of the provider, then add something thing to it before saving it to the database.

    On the other hand, if you want to change the state of the provider that is being watched by your ref.watch method, then you have to increment your state provider like this ref.read(pProvider.notifier).state++ this ensures that what your are incrementing is the state of the provider not the stored value. and this also triggers a rebuild on your widget because the state being watched is changing.

    Hope this helps explain your concern based on what I understood.