flutterdartflutter-bloccubit

How to add multiple state in one cubit in flutter bloc pattern?


I was developing an application in flutter which does OTP based authentication to log in. Earlier I was managing the states in the class itself so that I can use the setState method to render the UI accordingly. Then I changed into flutter_bloc cubit pattern to manage the states. But I fail to understand that how can I keep track of multiple states in one cubit.

Consider the following code of State and Cubit,


**State**.

@immutable
abstract class LoginState {}

class LoginInitial extends LoginState {
  final Map loginState;
  LoginInitial({this.loginState});
}

**Cubit**
class LoginCubit extends Cubit<LoginState> {
  Map loginState = {
    "isPhoneSubmitted": false,
    "isOtpArrived": false,
  };
  LoginCubit()
      : super(
          LoginInitial(
            loginState: {
              "isPhoneSubmitted": false,
              "isOtpArrived": false,
            },
          ),
        );

  void sendOtp() {
    emit(
      LoginInitial(
        loginState: {
          "isPhoneSubmitted": true,
          "isOtpArrived": false,
        },
      ),
    );
    Future.delayed(Duration(seconds: 4), () {
      emit(
        LoginInitial(
          loginState: {
            "isPhoneSubmitted": true,
            "isOtpArrived": true,
          },
        ),
      );
    });
  }
}

Here, Initially, I'm setting both values inside the map as false. And when the user clicks on the button setting the isPhoneSubmitted to true. And a few seconds later isOtpArrived to true(In future after getting OTP). However, I don't think this is the right approach to implement the pattern. Consider If I have 10 properties in a class and I'm sending a map of 10 properties each time when emit method is called.

Can someone help me understand or implement the best practice to hold/update multiple states to the widget the Cubit is listening to?

Also, in the widget, this is how I'm listening to the changes,

 BlocBuilder<LoginCubit, LoginState>(builder: (context, state) {
                final data = (state as LoginInitial).loginState;
                if (!data["isPhoneSubmitted"]) {
                  return phoneNumberSubmitWidget();
                } else {
                  return codeVerificationWidget();
                }
              }),

Solution

  • However, I don't think this is the right approach to implement the pattern.

    You are correct. The first step for complex state switches is to not use Cubit but an actual Bloc. Cubits are meant for very simple data with basically no state flow logic at all. Like an int. Or maybe a DarkTheme/LightTheme switch. Or maybe the language, where it can only ever be one and exactly one.

    But you have a complex flow. With "in-between" states. So use a Bloc and read the tutorial on this, in this case probable the login tutorial.