Comments (15)
Can confirm that this is a very common issue I see. I've onboarded multiple juniors onto riverpod, and they all make this mistake at least once.
from riverpod.
from riverpod.
can you please add a section in the docs clearly explaning this differences with code examples ?
from riverpod.
In some edge-cases you might want to watch the notifier, however, I agree that this is a super common issue for people who are new to Riverpod, and it should generally be discouraged. Any setup where you don't access a notifier via ref.read
whenever you want to use it is also often not the best way to do it I've noticed.
from riverpod.
Only valid cases when you want to watch notifier that I know of are onPressed: ref.watch(someProvider.notifier).fire
and
@override Widget build(BuildContext context, WidgetRef ref) {
final notifier = ref.watch(someProvider.notifier);
return Column(
children: [
Button(onPressed: () => notifier.fire('boom')),
Button(onPressed: () => notifier.fire('beep')),
]
);
}
from riverpod.
A bit surprised to see this as a warning, as they return different types. I don't see any case to watch a notifier, but we watch the state (AsyncValue) with a provider.
from riverpod.
To me, that's more a misuse of the notifier than a misuse of ref.watch
It is part of the good practices that Notifiers should not expose any state outside of its state
field.
There's already a warning telling users not to expose public getters/properties in their notifiers. That notifier.contains(...)
in the OP is similar to this. It just bypasses the linter because that's not a getter/property.
There are legitimate use-cases for ref.watch(provider.notifier), especially with the 3.0 where a new Notifier will be recreated when Notifier.build
is reinvoked.
Typically this is when using tear-offs:
final notifier = ref.watch(provider.notifier);
return Button(onTap: notifier.increment);
If the notifier were to be recreated, it should re-invoke the build method because the increment
method changed.
I could instead see a warning against using Notifier members within build
:
Widget build(ctx) {
final notifier = ref.watch(p.notifier); // OK, no warning
notifier.doSomething(); // KO, don't use notifier members inside build
}
from riverpod.
final notifier = ref.watch(provider.notifier); return Button(onTap: notifier.increment);
Wouldn't this also be less desirable than
return Button(onTap: ref.read(provider.notifier).increment);
due to the unnecessary rebuilds?
from riverpod.
Wouldn't this also be less desirable than
return Button(onTap: ref.read(provider.notifier).increment);due to the unnecessary rebuilds?
No that's incorrect.
Whatever rebuild we have here by using ref.watch
is necessary.
If the notifier instance changed, the button must have its onTap method changed to point to the new notifier.
Otherwise you'd be calling increment
on a disposed object.
from riverpod.
Oh, so in that case the tear-off points to an outdated function? That's crazy, I thought what I wrote would be equivalent to
return Button(onTap: () => ref.read(provider.notifier).increment());
Or am I crazy and that also wouldn't work?
Unrelated, but unnecessary_lambdas
is a bit misleading then.
from riverpod.
Nope, both variants aren't the same.
That's a common tear-off / variable dereference topic.
unnecessary_lambdas
The warning doesn't appear if a referenced variable is coming from an unknown source. There won't be such an issue here. Otherwise you would see the warning already when using ref.read
:)
from riverpod.
The warning doesn't appear if a referenced variable is coming from an unknown source. There won't be such an issue here. Otherwise you would see the warning already when using ref.read :)
That's why I said misleading, not wrong :) I'm gonna go out there and suspect that if you survey all Flutter devs, most would think that tear-offs are just syntactic sugar (in part because in some cases, their linter tells them to put them there), but maybe I'm projecting.
Anyway, thanks for the explanation!
from riverpod.
This is technically not coming from tear-offs, but how variables behave.
Consider:
int state = 0;
final previousState = state;
state++;
print('$previousState $state'); // prints "0 1"
That's why you should use ref.watch if you write:
final notifier = ref.watch(provider.notifier);
return Button(onTap: () => notifier.increment());
All of that will be covered by a separate lint that spots watch vs read mistakes.
from riverpod.
Hi @rrousselGit, thanks for the clarification! I'll keep in mind the differences between watching the provider and the notifier.
from riverpod.
can you please add a section in the docs clearly explaning this differences with code examples ?
Consider starting a new issue for this if there isn't already one.
from riverpod.
Related Issues (20)
- ImageProvider generated as InvalidType HOT 4
- `AutoDisposeProvider` is getting disposed when watched in a `StreamProvider` using `async*` HOT 1
- Provider container loses data in widget test HOT 4
- AutoDisposeNotifierProvider causing state loss HOT 3
- Reword `The ref.watch method should not be called asynchronously`
- Add a DevTools extension for riverpod HOT 2
- Broken update HOT 3
- [riverpod 3] NotifierProvider doesn't work with a NotifierBase mixin.
- riverpod_generator does not respect import aliases HOT 1
- Ref onError callback HOT 1
- `ref.exists()` returns `true` when manually invalidate a provider.
- `yarn dev -l {LANG}` is needed when hosting documentation website locally for specific locale with docusaurus
- Stream from StreamProvider is not unsubscribed to when widgets get disposed
- There is no way to handle the "done" event on the stream of a StreamProvider
- `ref.invalidate(familyProvider)` is not working with scoped providers
- PageController stateprovider doesn't work when .previousPage() or nextPage() is pressed
- beforeDispose or beforeInvalidate hook, happen before invalidate HOT 5
- Multiple invalidation of Providers HOT 1
- Unable to use the latest riverpod in flutter version lower than 3.16 HOT 2
- The getter 'variable2' isn't defined for the class 'PropertyAccessorElement'. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from riverpod.