I have a use-case that got me a bit confused in the way I understood Provider or Navigation.
So I have two views with scoped Providers, which are StateNotifierProiders to be precise.
QuizView and SelectedQuizView
The quiz view has a list of tiles on selecting navigates to that selected information with more info. Now, on both of these, I am managing the state of favorites since they can be marked as a favourite or not favorite which should update in both thee views.
Since SelectedQuizView is inside of QuizView in the during navigation, I thought the StateNotifier, QuizVM which is scoped to QuizView should have been created and exists.
So I did what I thought was the most logical thing and did this
StateNotifierProvider<QuizVM,QuizState>.value(
value: QuizVM
child SelectedQuizView( )
Since QuizVM was already created. Now I was able to access QuizVM but it seemed to be a new instance as the state was reverted to loading and I thought it should be Loaded since it was set in the previous view.
While at this I got another Exception DependencyNotFoundException from read<Repositiry> which made me even more confused because this Repository is a global Provider.
I solved this by a Workaround of making QuizVM a global Provider and giving SelectedQuizView its own StateNotifier.
But I'm curious as to what I was doing wrong. And would like to know. Can you please give me a better understanding?
Thank you!
@rrousselGit Can you please help me with this? I still have not been able to figure it out
Is your StateNotifierProvider above MaterialApp? That's usually the problem
@rrousselGit , No, My StateNotifierProvider was scoped to only one screen. Moving it above MaterialApp Solved my problem.
I wanted to access the same instance of StateNotifier that is Scoped to one screen, in another screen which in navigated to.
Which I tought I could by using StateNotifierProvider.value( ), I was able to but it was a different instance since the initial sate was set again, this is where I am stuck
I wouldn't recommend scoping providers to a route. That's very rarely a good idea.
@rrousselGit, I don't usually do, but for some views, I want the state to be reset when I pop the screen. So all the data is reset in that state the next time it's opened.
I had this problem when I had all my providers above MaterialApp. So I stuck to scoped providers.
Can you suggest an alternative if this isn't the best approach ?
Instead you can have a StatefulWidget in your route and override its State.dispose to reset the model state:
class Model extends ChangeNotifier {
int count =0;
void reset() {
count = 0;
}
}
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Model model;
@override
void didChangeDependencies() {
super.didChangeDependencies();
model = context.watch<Model>();
}
@override
Widget build(BuildContext context) {
return Container();
}
@override
void dispose() {
model.reset();
super.dispose();
}
}
Thanks. That's a good option.
But I try to avoid all the Statefull widget mess and use Hooks for any such use case of state.
Is there anyway I can achieve the same with useEffect() ? If so could you tell me more ?
I'm trying to figure out all the options.
sure:
final model = context.watch<Model>();
useEffect(() {
return model.reset;
}, [model]);
@rrousselGit Thank you so much, I will try this out.
Most helpful comment
Instead you can have a
StatefulWidgetin your route and override itsState.disposeto reset the model state: