Home > Software design >  Flutter Provider with listen false, but still get error "setState() or markNeedsBuild() called
Flutter Provider with listen false, but still get error "setState() or markNeedsBuild() called

Time:10-20

I would like to reset userProvider when networkProvider changes. In the userProvider.reset(), I have notifyListeners.

void didChangeDependencies() async {
  super.didChangeDependencies();
  final NetworkProvider networkProvider = Provider.of<NetworkProvider>(context);
  UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
  userProvider.reset(); }

When it runs, it gives error "setState() or markNeedsBuild() called during build." My question is, I have set the listen to false, why it still rebuild this widget?

When there is only a UserProvider, it has the same error:

void didChangeDependencies() async {
  super.didChangeDependencies();
  UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
  userProvider.reset(); }

If my idea of usage is totally wrong, is there any suggestion to achieve the same result?

CodePudding user response:

Because you mention that NetworkProvider changes, I'm guessing it's also publishing notifications in which case you'd also want this to not trigger rebuilds with the listen: false parameter. It seems like you do want those notifications though so that you can reset your UserProvider. I would suggest that you don't try and do this in a Widget's lifecycle but use a ProxyProvider to create and update your UserProvider with it being dependent on the NetworkProvider.

CodePudding user response:

All right, I found the answer. It is writen in latter of their home page. What I tried in my question is not allowed, because the state update is synchronous.

This means that some widgets may build before the mutation happens (getting an old value), while other widgets will build after the mutation is complete (getting a new value). This could cause inconsistencies in your UI and is therefore not allowed.

Instead, you should perform that mutation in a place that would affect the entire tree equally:

class MyNotifier with ChangeNotifier {
  MyNotifier() {
  _fetchSomething();
}

Future<void> _fetchSomething() async {
}

To use it in build:

Future.microtask(() =>
    context.read<MyNotifier>().fetchSomething(someValue);
);
  • Related