rrousselGit / state_notifier

ValueNotifier, but outside Flutter and with some extra perks
MIT License
311 stars 28 forks source link

State changes on page load #37

Closed sderungs99 closed 3 years ago

sderungs99 commented 3 years ago

Describe what scenario you think is uncovered by the existing examples/articles I'd like to use a StateNotifier on page load (not on any specific user interaction on the page itself). Currently, I am using initState on the StateNotifier, which fetches data from a remote server. The issue I am facing is that this is only executed once, and not each time I am navigating to the page.

Describe why existing examples/articles do not cover this case I am assuming the above is the intended behaviour (i.e. initState is only executed once, when creating the StateNotifier). If that is the case, what is the recommended implementation for my use case described above?

sderungs99 commented 3 years ago

One way I just realised to do this is to change my view to a stateful view, rather than stateless view, and in the view widget's initState method I then call a method in the StateNotifier, which does what it was doing before in its own initState function. That way, every time the view is loaded, it executes the method.

It does "feel wrong", though, as StateNotifier/Provider should eliminate the need for stateful widgets. Or maybe I am completely wrong here? :-)

rrousselGit commented 3 years ago

Have you tried "StateNotifierProvider.autoDispose"?

sderungs99 commented 3 years ago

Is that available for riverpod only? I am not using riverpod (yet?), but provider/state_notifier/flutter_state_notifier and I am setting up my providers like so:

MultiProvider(
  providers: [
    StateNotifierProvider<EventsViewModel, EventsViewModelState>(
      create: (_) => EventsViewModel(),
    ),
  ]
  child: MaterialApp(...)
)

Using the above method, StateNotifierProvider.autoDispose does not seem to be an option, unless I am using it wrong? This is what I tried:

MultiProvider(
  providers: [
    StateNotifierProvider.autoDispose<EventsViewModel, EventsViewModelState>(
      create: (_) => EventsViewModel(),
    ),
  ]
  child: MaterialApp(...)
)
rrousselGit commented 3 years ago

Oh my bad I didn't realize that with was the state_notifier repository

Yes this is available only in Riverpod

For provider, you will need a StatefulWidget as you mentioned

sderungs99 commented 3 years ago

Thanks! Although, I must still be missing something and do something wrong.

If I understand it correct, I would store the state in my State Notifier, similar to so:

void myInitialise() async {
  // fetch some data
  ...
  //store the result in the state
  state = MyState(...);
}

Then in the StateFull view, I would call this during initState:

@override
void initState() {
  context.read<MyNotifier>().myInitialise();
  super.initState();
}

And in the build method of that same view, I watch for changes:

final watchMyNotifier = context.watch<MyNotifier>();

When trying like that, I am getting following error: flutter: setState() or markNeedsBuild() called during build.

Where am I going wrong here?

sderungs99 commented 3 years ago

I got it fully working by using:

@override
void initState() {
  Future.microtask(() => context.read<MyNotifier>().myInitialise());
  super.initState();
}

Is that the right way? I have to admit, I don't fully understand why that would work and the other way not! :-)

rrousselGit commented 3 years ago

That's fine

You cannot synchronously update your providers inside widget lifecycles

sderungs99 commented 3 years ago

Thank you. In that case, issue can be closed :-)