Bloc: simple implementation to handle click event with Bloc work once

Created on 19 May 2019  路  3Comments  路  Source: felangel/bloc

I have some separated view class as App and MainPage and i implemented simple Bloc pattern to handle click event on some widgets such as button and another problem is when i run application i get message in console without click on widgets :|

after running application my implemented bloc pattern only work once and show message in console and after click again that don't work to show message

my main.dart class

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    title: Strings.appName,
    theme: ThemeData(
      primarySwatch: Colors.indigo,
    ),
    home: App(),
  ));
}

class App extends StatefulWidget {
  final HomeBloc homeBloc = HomeBloc();

  @override
  State<App> createState() => MainPage();
}

MainPage class:

class MainPage extends State<App> {
  @override
  void initState() {
    super.initState();
  }

  HomeBloc get _homeBloc => widget.homeBloc;

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: Strings.appName,
      theme: ThemeData(
        primarySwatch: Colors.indigo,
      ),
      home: BlocBuilder<HomeEvent,HomeState>(
          bloc: _homeBloc,
          builder: (BuildContext context, HomeState state) {
            if (state is HandleDrawerMenuClick) {
              _onWidgetDidBuild(() {
                print("clicked on drawer menu");
              });
            }

            return Scaffold(
              body: Center(
                child: RaisedButton(
                  child: Text('ddddddddd'),
                  onPressed: () {
                    _homeBloc.dispatch(OnDrawerMenuClicked());
                  },
                ),
              ),
            );
          }),
    );
  }

  @override
  void dispose() {
    _homeBloc.dispose();
    super.dispose();
  }

  void _onWidgetDidBuild(Function callback) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      callback();
    });
  }
}

HomeBloc class:

class HomeBloc extends Bloc<HomeEvent, HomeState> {
  @override
  HomeState get initialState => HomeState();

  @override
  Stream<HomeState> mapEventToState(HomeEvent event) async* {
    if (event is OnDrawerMenuClicked) {
      yield HandleDrawerMenuClick();
    }
  }
}

HomeEvent class:

class HomeEvent extends Equatable {
  HomeEvent([List props = const []]) : super(props);
}

class OnDrawerMenuClicked extends HomeEvent {
  OnDrawerMenuClicked() : super([]);

  @override
  String toString() => 'OnDrawerMenuClicked clicked';
}

HomeState class:

class HomeState extends Equatable{
  HomeState([List props = const[]]):super(props);
}

class HandleDrawerMenuClick extends HomeState{
  @override
  String toString()=>'HandleDrawerMenuClick';
}

i think problem is on HandleDrawerMenuClick class because when i debug application, debug can go into if statement on this line:

if (event is OnDrawerMenuClicked) {
  yield HandleDrawerMenuClick();
}

and i think twice click on button couldn't trigger yield HandleDrawerMenuClick();

question

Most helpful comment

No problem!

That鈥檚 fine but just make sure BlocBuilder is only used to return widgets based on states. Any other code like navigation, showing a dialog, etc... doesn鈥檛 belong in BlocBuilder and should be done in BlocListener instead.

All 3 comments

Hi @MahdiPishguy 馃憢
Thanks for opening an issue.

This is because once you click on the button once, the event is dispatched and you yield HandleDrawerMenuClick. Then if you dispatch again, the state is already HandleDrawerMenuClick. If you want it to trigger every time even though the state hasn鈥檛 changed you should not extend Equatable. Also you should use BlocListener to handle the DrawerMenuClick instead of doing it in BlocBuilder.

Check out the snack bar recipe for an example of how and why to use BlocListener.

Hope that helps! 馃憤

@felangel thanks

i'm trying to implementing simple your login project and i need to have BlocBuilder without using Authentication implementation

No problem!

That鈥檚 fine but just make sure BlocBuilder is only used to return widgets based on states. Any other code like navigation, showing a dialog, etc... doesn鈥檛 belong in BlocBuilder and should be done in BlocListener instead.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

clicksocial picture clicksocial  路  3Comments

rsnider19 picture rsnider19  路  3Comments

Reidond picture Reidond  路  3Comments

hivesey picture hivesey  路  3Comments

nhwilly picture nhwilly  路  3Comments