how to make bloc stream listens all the time?

53 views Asked by At

i am made an api for login and trying that on flutter using flutter_bloc i have success fully connected api and is working . for the first time state is being reactive and i see the result on my screen. for example i add email and password . i enter wrong email frmat and i submitted the i do get validation error seen on my screen and if i try sending same request again the api gets it but my state doesnot channge for some reason

void _handleSubmit() {
    Map<String, dynamic> formData = fieldValuesNotifier.value;
    final authBloc= context.read<AuthBloc>();
    authBloc.add(
        LoginUser(
            formData['email'],
            formData['password']
        )
    );
    authBloc.stream.listen((state) {
       **// this line of code works when i hit api first time but not for second time //**  
      if (state is UserLoggedIn) {
        AutoRouter.of(context).popAndPush(const Motivation());
      }
      else if(state is ValidationErrors){
        setState(() {
          for (int i = 0; i < formFields.length; i++) {
            String field = formFields[i]['field'];
            if (state.validationErrors.containsKey(field)) {
              formFields[i]['error'] = state.validationErrors[field][0].toString();
            }
          }
        });

      }
    });
  }

i am triyng to make the state reactive so it can reacte to the changes i am doing

1

There are 1 answers

1
Jhonatan On

You're using directly the bloc stream in order to listen the bloc state changes and updating the widgets with setState(...). It's not a good idea. The right way to use bloc is using BlocBuilder to update the widgets. It's all you need. https://medium.com/flutter-community/flutter-bloc-for-beginners-839e22adb9f5 Here is a good example on how to use bloc and blocbuilder.

If you need to do changes or functions based on the bloc states, use Widgetsbinding.instance.addPostFrameCallback method to avoid problems and collisions with the widget build method. Something like this:

Widgetsbinding.instance.addPostFrameCallbacks((){
   if (state is UserLoggedIn) {
      AutoRouter.of(context).popAndPush(const Motivation());
    }
    else if(state is ValidationErrors){
      //But, again, don't use setState to do the same thing blocBuilder could do
      setState(() {
        for (int i = 0; i < formFields.length; i++) {
          String field = formFields[i]['field'];
          if (state.validationErrors.containsKey(field)) {
            formFields[i]['error'] = state.validationErrors[field][0].toString();
          }
        }
      });
    }
});