Bloc: State not change when event called

Created on 11 Feb 2020  路  2Comments  路  Source: felangel/bloc

Hi,
I have a screen that user must write his mobile number on the input.
I use bloc in this screen.
Base on initial state everything work.
but when an event called nothing change.

here is my bloc:

class MobileVerifyBloc extends Bloc<MobileVerifyEvent, MobileVerifyState> {
    final MobileVerifyRepository mobileVerifyRepository;
    MobileVerifyBloc({this.mobileVerifyRepository}) : assert(mobileVerifyRepository != null);
  @override
  MobileVerifyState get initialState => MobileVerifyInitial();

  @override
  Stream<MobileVerifyState> mapEventToState(MobileVerifyEvent event) async* {
        print('come here');
        if (event is MobileVerifyInputChanged) {
            print(event.mobile);
            mobileVerifyRepository.setMobile(event.mobile);
            yield MobileVerifyMobile(mobile: event.mobile);
        }
    if (event is MobileVerifyButtonPressed) {
            print('come here2');
      yield MobileVerifyLoading();
      try {
                // TODO Call API
        yield MobileVerifyInitial();
      } catch (error) {
        yield MobileVerifyFailure(error: error.toString());
      }
    }
  }
}

and event:

abstract class MobileVerifyEvent extends Equatable {
  const MobileVerifyEvent();
}

class MobileVerifyButtonPressed extends MobileVerifyEvent {
  final String mobile;

  const MobileVerifyButtonPressed({
    @required this.mobile,
  });

  @override
  List<Object> get props => [mobile];

  @override
  String toString() => 'MobileVerifyButtonPressed { mobile: $mobile }';
}

class MobileVerifyInputChanged extends MobileVerifyEvent {
  final String mobile;

  const MobileVerifyInputChanged({
    @required this.mobile,
  });

  @override
  List<Object> get props => [mobile];

  @override
  String toString() => 'MobileVerifyButtonPressed { mobile: $mobile }';
}

and state:

abstract class MobileVerifyState extends Equatable {
  const MobileVerifyState();

  @override
  List<Object> get props => [];
}

// bloc initialize
class MobileVerifyInitial extends MobileVerifyState {}

class MobileVerifyValidateSuccessfull extends MobileVerifyState {}

class MobileVerifyMobile extends MobileVerifyState {
    final String mobile;
    const MobileVerifyMobile({@required this.mobile});
  @override
  List<Object> get props => [mobile];

  @override
  String toString() => 'MobileVerifyError { error $mobile }';
}

// Mobile validation failed
class MobileVerifyError extends MobileVerifyState {
  final String error;
  const MobileVerifyError({@required this.error});
  @override
  List<Object> get props => [error];

  @override
  String toString() => 'MobileVerifyError { error $error }';
}

// API is called
class MobileVerifyLoading extends MobileVerifyState {}

// API called failed
class MobileVerifyFailure extends MobileVerifyState {
  final String error;

  const MobileVerifyFailure({@required this.error});

  @override
  List<Object> get props => [error];

  @override
  String toString() => 'MobileVerifyFailure { error: $error }';
}

// API is OK
class MobileVerifySuccessful extends MobileVerifyState {}

this is my repository:

class MobileVerifyRepository {
  String mobile;
    void setMobile(mobile) {
        this.mobile = mobile;
    }
}

and my UI where I use bloc:

class MobileVeifyScreen extends StatelessWidget {
  final _formKey = GlobalKey<FormState>();
  final bool _autoValidate = false;
  final _mobileController = TextEditingController();
  final MobileVerifyRepository mobileVerifyRepository = MobileVerifyRepository();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: ColorPalette.verifyMobileBC,
      body: Builder(
        builder: (context) {
          return BlocProvider(
            create: (context) {
              return MobileVerifyBloc(mobileVerifyRepository: mobileVerifyRepository);
            },
            child: BlocListener<MobileVerifyBloc, MobileVerifyState>(
              listener: (context, state) {
                if (state is MobileVerifyFailure) {
                  Scaffold.of(context).showSnackBar(
                    SnackBar(
                      content: Text('${state.error}'),
                      backgroundColor: Colors.red,
                    ),
                  );
                }
              },
              child: BlocBuilder<MobileVerifyBloc, MobileVerifyState>(
                builder: (context, state) => Scroll(
                  child: AuthCard(
                    image: Assets.mobileVerify,
                    title: Strings.mobileVerifyTitle,
                    render: Column(
                      children: <Widget>[
                        Form(
                          autovalidate: _autoValidate,
                          key: _formKey,
                          child: Container(
                            width: 300.0,
                            child: Input(
                              controller: _mobileController,
                              textAlign: TextAlign.left,
                              inErr: state is MobileVerifyError,
                              hintText: Strings.mobileHint,
                                                            onChanged: (value) => MobileVerifyInputChanged(mobile: value),
                              keyboardType: 'number',
                              maxLength: 11,
                              prefixIcon: Icons.done,
                              prefixIconColor: (state is MobileVerifyValidateSuccessfull) ? Colors.green : Colors.grey,
                              isSuccess: (state is MobileVerifyValidateSuccessfull) ? true : false,
                            ),
                          ),
                        ),
                                                RaisedButton(
                                                    onPressed: () => MobileVerifyButtonPressed(mobile: _mobileController.text),
                                                    child: Text('click'),
                                                )
                      ],
                    ),
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

It seem my mapEventToState not called at all.
What's my problem?

question

Most helpful comment

You are using this package wrong. You have to call myBloc.add(myEvent) method, not only return event, which will do, of course, nothing.

E.g. instead of

RaisedButton(
  onPressed: () => MobileVerifyButtonPressed(mobile: _mobileController.text),
  child: Text('click'),
)

you should do

RaisedButton(
  onPressed: () => BlocProvider.of<MobileVerifyBloc>(context).add(MobileVerifyButtonPressed(mobile: _mobileController.text)),
  child: Text('click'),
)

For more information, see https://bloclibrary.dev/#/flutterbloccoreconcepts

All 2 comments

You are using this package wrong. You have to call myBloc.add(myEvent) method, not only return event, which will do, of course, nothing.

E.g. instead of

RaisedButton(
  onPressed: () => MobileVerifyButtonPressed(mobile: _mobileController.text),
  child: Text('click'),
)

you should do

RaisedButton(
  onPressed: () => BlocProvider.of<MobileVerifyBloc>(context).add(MobileVerifyButtonPressed(mobile: _mobileController.text)),
  child: Text('click'),
)

For more information, see https://bloclibrary.dev/#/flutterbloccoreconcepts

@tenhobi
yes, tnx for reply and help.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rsnider19 picture rsnider19  路  3Comments

RobPFarley picture RobPFarley  路  3Comments

tigranhov picture tigranhov  路  3Comments

nhwilly picture nhwilly  路  3Comments

wheel1992 picture wheel1992  路  3Comments