I was exploring the possibility of adding riverpod to some parts of my existing project which uses provider at the moment.
One of my current providers from the provider package is the theme of the app with custom colors and such.
From any of my widgets I can do Provider.of<MyTheme>(context). I was wondering if there is a way of watching a specific riverpod provider by its name, without relying on Consumer or ConsumerWidget.
Something along the lines of:
static MyTheme of(BuildContext context){
return ProviderScope.containerOf(context).watch(_myThemeProvider);
}
I find migrating my current MyTheme dependency to riverpod very hard or nearly impossible if using Consumer/ConsumerWidget/useProvider is the only solution because many of my widgets depend on the signature from above.
Migrating to using Consumers can be doable but not for moderately sized projects.
This is not feasible and is in fact one of the reasons why Riverpod and Provider are separated.
This would both significantly reduce the performances and remove some features (like ".autoDispose")
The question would instead be:
Why is it hard for you to migrate to Consumer/ConsumerWidget/useProvider?
I totally understand if this is not feasible at all to do. I just wanted to share my experience from an existent Provider project standpoint.
The question would instead be:
Why is it hard for you to migrate to Consumer/ConsumerWidget/useProvider?
Simply put:
Big project with many different widgets. Error prone to update all that code.
How so?
You'd have a compile error if you made a mistake
I guess that's true thanks to the compile safety from riverpod.
In some situations it's not so linear.
If you have StatefullWidget's where you mix setState and Provider it's a little bit harder to just migrate to ConsumerWidget or Consumer
In my case, when i had just a simple inner state, i converted to a ConsumerWidget and created a private StateProvider and used it instead of setState. In other cases where that provider state could be used in isolation, i just used a Consumer widget.
But i ended up being able to migrate our App to river_pod, replacing Provider and get_it with it! Thanks allot for your work on all of this, by the way!
@porfirioribeiro Couldn't you just turn your StatefulWidget into a ConsumerWidget? I think you could still use setState because ConsumerWidget extends from StatefulWidget
In some situations it's not so linear.
Could you give examples of those situations? One long-term plan is to make a script to automatically convert from provider to riverpod, so that would be really helpful
Also, in the short term, I want to release a migration guide. "Riverpod for Provider users" or something like that
So if you could list your pain points, I'll make sure to cover them
In some situations it's not so linear.
Could you give examples of those situations? One long-term plan is to make a script to automatically convert from provider to riverpod, so that would be really helpful
Well, provider can be injected in any widget type, so you could access it either on StatelessWidget or StatefulWidget
For river_pod you need to change your widget either to ConsumerWidget/HooksWidget or wrap it in a Consumer
When using StatelessWidget was really straightforward to migrate to ConsumerWidget, (i didn't want to also bring flutter_hooks to the project, maybe later, need to investigate it more )
Now when you have a SatefulWidget because of some setState or some controllers its a little more complicated.
@davidmartos96 Even tho ConsumerWidget extends StatefulWidget you are extending the Widget not the State, so it does not work as a StatefulWidget, in my understanding.
@porfirioribeiro Oh you are totally right.
Could you expand on the difficulties encountered with StatefulWidget?
I think the issue stems from the docs not really every explaining how to use this with a Stateful Widget.
If I understand right, this is functionally equivalent to a ConsumerWidget??
class _MyWidgetState extends State<MyWidget> {
Widget build(BuildContext context) {
return Consumer(
builder: (context, watch, _) {
bool value = watch(myModel).value;
return ...;
}
)
}
}
If that's true, then migrating from Provider shouldn't be tooo hard.
The two main issue here are
watch() method can presumably be used on multiple providers. But still, lots of lines, spaces and brackets compared to context.watchIn general I just find it very odd that we have a context.read for button handlers, but then can't have context.watch or context.select inside a stateful widget.
I also still don't full understand how we're supposed to access a provider from outside the widget tree completely, for instance if we want to implement our Application Logic using simple Command objects. Do we have to create a Container each time, just to do the read?
There's just so much going on, and so many options, and so many flavors or implicit references to other packages, it just makes it really hard to see the clear path forward when learning riverpod.
@esDotDev Yes accessing provider from outside widget tree using the Container is not clear to me either, and there is not much on the docs regarding that.
cc @rrousselGit
Using flutter_hooks, even if only for hooks_riverpod, will really simplify the process of using riverpod for many users. It eliminates the nesting among other pain points that seem to be coming up with adopting riverpod.
There is StatefulHookWidget for those who really want to maintain verbose syntax using StatefulWidget for their state while gaining simpler usage of riverpod. Then, when you are ready to embrace concise state management, it would be possible to remove Stateful widget by widget as you convert the remaining state to use hooks.
An added bonus is that @rrousselGit examples are usually using hooks, freezed, and riverpod in conjunction, so if you learn by example, it's a good idea to go that route. I have really been enjoying the luxuries afforded by utilizing these great packages in tandem.
The argument isn't that switching over to a fully hooks-based approach is not going to simplify usage, it's that it greatly complicates understanding required before usage can occur. Assuming you're someone who likes to understand how code works, and why you're extending the classes you're extending.
First should be clear demonstrations of the 'un-simplified' process, so riverpod can be evaluated on it's own terms, using some common workflows. And then, if examples are provided of accelerators using additional libs, that would be great.
Fair enough, I would still stand by the point that many if not all concerns I've seen are solved by using hooks though. Yes, more examples of non-hooks riverpod would be great, but it's definitely a case of stepping backwards to move forwards.
It seems more to me like a Flutter problem than a riverpod/hooks problem. The copious boilerplate required by vanilla Flutter (that vanilla riverpod is directly affected by) is all solved when using the simpler, more concise, hooks approach to building widgets. There are also really complex architectures that are being popularized for whatever reason that get people confused when working with riverpod/provider as well.
All that said, I'm sure everyone would welcome a contribution of an example using riverpod without hooks.
Tutorials will be available in due time (not just examples, but code with the explanation)
I'll make sure that all the tutorials I write will be available both with and without hooks. Not just so that people can start slowly, but also compare approaches.
I probably won't be using ChangeNotifier though, and focus on StateNotifier + Freezed, and instead will make a single "ChangeNotifier vs StateNotifier" article
@rrousselGit Would it be feasible to implement a custom hook called useWatch? It would return a ScopedReader, same as ConsumerWidget. That would make migrating StatefulWidgets easier with the help of StatefulHookWidget + avoiding unnecessary nesting in the process as @esDotDev mentioned previously.
What would be the benefit over useProvider?
Oh, nevermind. I wasn't thinking about useProvider. That could be used as well.
Most helpful comment
Tutorials will be available in due time (not just examples, but code with the explanation)
I'll make sure that all the tutorials I write will be available both with and without hooks. Not just so that people can start slowly, but also compare approaches.
I probably won't be using
ChangeNotifierthough, and focus onStateNotifier+ Freezed, and instead will make a single "ChangeNotifier vs StateNotifier" article