Bloc: setState() or markNeedsBuild() called during build

Created on 24 Apr 2020  路  3Comments  路  Source: felangel/bloc

I am using bloc to handling app state so this is my bloc class:

 @override
  Stream<FoursquareState> mapEventToState(
    FoursquareEvent event,
  ) async* {
    if (event is GetVenuesByUserEvent) {
      yield Loading();
      try {
        List<VenuesMapModel> venuesList = List();
        final result = await repo.getVenuesByUser(event.lat, event.lng);
        yield Loaded(result);
      } on Exception catch (e) {
        yield Error(e.toString());
      }
    } else if (event is GetVenuesDetailsEvent) {
      yield Loading();
      try {
        final result = await repo.getVenuesDetails(event.venueId);
        yield LoadedDetails(result);
      } on Exception catch (e) {
        yield Error(e.toString());
      }
    }
  }

In my builder i write this codes:

    return Scaffold(
        appBar: AppBar(),
        body: SafeArea(
          child: BlocBuilder<FoursquareBloc, FoursquareState>(
            builder: (ctx, state) {
              if (state is Loading) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else if (state is LoadedDetails) {
                print("LoadedDetails is loaded");
                return _venueCard(state.venuesDetail);
              }else if(state is Error){
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (ctx) => ErrorScreen())
                );
              }
              return Container();
            },
          )

But when Error state is called in this section :

 Navigator.of(context).push(
                  MaterialPageRoute(builder: (ctx) => ErrorScreen())

I got this error:

The following assertion was thrown building BlocBuilder<FoursquareBloc, FoursquareState>(dirty, state: _BlocBuilderBaseState<FoursquareBloc, FoursquareState>#a4ea3):
setState() or markNeedsBuild() called during build.

This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#4af7f]
    state: OverlayState#1ca13(entries: [OverlayEntry#106a4(opaque: true; maintainState: false), OverlayEntry#54ef7(opaque: false; maintainState: true), OverlayEntry#1ea85(opaque: true; maintainState: false), OverlayEntry#08341(opaque: false; maintainState: true), OverlayEntry#c583f(opaque: false; maintainState: false), OverlayEntry#313fc(opaque: false; maintainState: true)])
question

Most helpful comment

@tazik561 check out BlocListener for this. You shouldn't be performing side-effects in BlocBuilder. See this recipe for more info.

All 3 comments

@tazik561 you can avoid that using scheduleMicrotask(() => Navigator.of(context).push( MaterialPageRoute(builder: (ctx) => ErrorScreen()) ));

Edit: thought it was a listener not builder, please ignore my suggestion then. You should definitely be using a listener for side effects.

That is mean i can not to change route?
Then how can i change page according some condition in bloc state?

@tazik561 check out BlocListener for this. You shouldn't be performing side-effects in BlocBuilder. See this recipe for more info.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

komapeb picture komapeb  路  3Comments

rsnider19 picture rsnider19  路  3Comments

krusek picture krusek  路  3Comments

abinvp picture abinvp  路  3Comments

wheel1992 picture wheel1992  路  3Comments