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
.
CodePudding user response:
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.
CodePudding user response:
ref.read
and ref.watch
are different:
We use ref.read
to get the provider's value once (one-time read).
We use ref.watch
to get the provider's value the first time and every time the value changes (watch it as if you subscribed to the provider, so you'll be notified of changes at any time).
You don't need to always get the value, you should only get the provider's value once.
Update:
I suggest you use p
elsewhere and use ref.watch(myProvider).doSomething()
in the onPressed
function.