Proper use of cubit

Issue

I am still learning how to use cubit and bloc, and I am trying to use a cubit in my project, but I got a little bit confuse about how to use it.

There is a screen that requires a phone number and I use the lib "intl_phone_number_input" to format, validate and select the country. When I click the button to next page it needs to check if the phone is valid, but I need to have a variable that stores this info. The widged InternationalPhoneNumberInput has a property onInputValidated that returns true if the phone number is valid, so where should I create this variable? Should I create it in my widget class or inside cubit? I created inside cubit but I am not sure if it is the correct way, so I got this:

onInputValidated: (bool value) {
  BlocProvider.of<LoginCubit>(context).isValid =
    value;
},

I’ve studied and seen some examples about cubit and how to use’em but I still didn’t get it at all, because in the examples the cubit never used a variable, all variables became a state, but in my case I need the value as variable.

I am confuse too about how to show a dialog using cubit, I’ve done this way:

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<LoginCubit, LoginState>(
      listenWhen: (previous, current) => current is ShowDialogErrorLoginState || current is NavigateFromLoginStateToHomePageState,
      listener: (context, state) {
        if (state is ShowDialogErrorLoginState) {
          showErrorDialog(context, state.titleMessage, state.bodyMessage);
        }
        if (state is NavigateFromLoginStateToHomePageState) {
          Navigator.pushReplacement(context,
              MaterialPageRoute(builder: (context) => const MyHomePage()));
        }
      },
      builder: (context, state) {
        if (state is ShowLoginState) {
          return buildPhoneForm(context);
        }
        if (state is SendingCodeLoginState) {
          return ProgressView(message: 'Sending SMS code',);
        }
        if (state is ShowCodeLoginState) {
          return buildCodeForm(context);
        }
        return const ErrorView('Unknown error');
      },
    );
  }

and in my cubit I did the following:

  void goToCodeVerification(String phoneNumber) async {
    if (!isValid){
      String titleMessage = "Phone number invalid";
      String bodyMessage = "The given phone number is invalid";

      emit(ShowDialogErrorLoginState(titleMessage, bodyMessage));
      emit(ShowLoginState());
    } else {
      emit(SendingCodeLoginState());
      // TO DO
      // use API to send a code
      emit(ShowCodeLoginState());
    }
  }

Is this the correct way to show a dialog with cubit?

Solution

Ok, so you have a value you want to use, the variable doesn’t affect state, and you need to access it inside your cubit.

for something like this, I think storing the variable on the cubit makes the most sense, but keep in mind either approach is acceptable for such a simple case.

I also don’t really like how the below code looks:

onInputValidated: (bool value) {
  BlocProvider.of<LoginCubit>(context).isValid =
    value;
},

it is a bit clunky, I would prefer to move the whole callback into the cubit:

void onInputValidated(bool value) => isValid = value;

that way:

final cubit = BlocProvider.of<LoginCubit>(context);
...
onInputValidated: cubit.onInputValidated,

Answered By – h8moss

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *