flutterblocflutter-bloccubitflutter-cubit

flutter_bloc is it ok to store a variable inside bloc/cubit class


i have a cubit named AuthCubit in which I have multiple functions related to authentication like login,resetPassword,...

the thing is all my functions need variable phoneNumber which is taken from user on on first screen, after checking if phoneNumber exists in server or not application navigates to different screens.

so my question is that is it ok to store phoneNumber in AuthCubit class and use it from there (like how it's done with Provider/ChangeNotifier)? or should I make AuthState base class require a phoneNumber variable?

below is the code snippet from AuthCubit

class AuthCubit extends Cubit<AuthState> {
  final LoginWithCredentialsUsecase _loginWithCredentialsUsecase;
  final CheckPhoneNumberExistUsecase _checkPhoneNumberExistUsecase;
  final SendOTPTokenUsecase _sendOTPTokenUsecase;
  final VerifyOTPTokenUsecase _verifyOTPTokenUsecase;
  final SendResetPasswordOtpUsecase _sendResetPasswordOtpUsecase;
  AuthCubit(
      {required LoginWithCredentialsUsecase loginWithCredentialsUsecase,
      required CheckPhoneNumberExistUsecase checkPhoneNumberExistUsecase,
      required SendOTPTokenUsecase sendOTPTokenUsecase,
      required VerifyOTPTokenUsecase verifyOTPTokenUsecase,
      required SendResetPasswordOtpUsecase sendResetPasswordOtpUsecase,
      required VerifyResetPasswordOtpUsecase verifyResetPasswordOtpUsecase})
      : _loginWithCredentialsUsecase = loginWithCredentialsUsecase,
        _checkPhoneNumberExistUsecase = checkPhoneNumberExistUsecase,
        _sendOTPTokenUsecase = sendOTPTokenUsecase,
        _verifyOTPTokenUsecase = verifyOTPTokenUsecase,
        _sendResetPasswordOtpUsecase = sendResetPasswordOtpUsecase,
        super(AuthInitial());
 
  Future<void> loginWithCredentianls(
      {String password = '',
      required String phoneNumber,
      String otpCode = ''}) async {
    emit(AuthLoading());
    try {
      final driver = await _loginWithCredentialsUsecase(
          password: password, phoneNumber: phoneNumber, otpCode: otpCode);
      emit(AuthSuccess(driver: driver));
    } on LoginFieldsNotCorrectException catch (e) {
      emit(AuthException(message: e.message));
    } on LoginNoRemainingChangeDeviceException catch (e) {
      emit(AuthException(message: e.message));
    } on LoginNotADriverException catch (e) {
      emit(AuthException(message: e.message));
    } catch (e) {
      emit(AuthFailed(message: e.toString()));
    }
  }

  Future<void> sendOTPMessageToPhoneNumber(String phoneNumber) async {
    emit(AuthLoading());
    try {
      final wasSuccess = await _sendOTPTokenUsecase(phoneNumber);
      if (wasSuccess) {
        emit(PhoneAuthOTPSent(phoneNumber: phoneNumber));
      } else {
        emit(phoneAuthFailedState);
      }
    } catch (e) {
      emit(phoneAuthFailedState);
    }
  }

  Future<void> checkPhoneAuthentication(String phoneNumber) async {
    emit(AuthLoading());
    try {
      final phoneNumberAuth = await _checkPhoneNumberExistUsecase(phoneNumber);
      if (phoneNumberAuth.isAuthenticated) {
        emit(PhoneAuthenticated(phoneNumber: phoneNumber));
      } else {
        emit(PhoneNotAuthenticated(
            message: phoneNumberAuth.message, phoneNumber: phoneNumber));
      }
    } catch (error) {
      emit(phoneAuthFailedState);
    }
  }

  Future<void> verifyOTPToken(String token, String phoneNumber) async {
    emit(AuthLoading());
    try {
      final wasSuccess = await _verifyOTPTokenUsecase(token, phoneNumber);
      if (wasSuccess) {
        emit(PhoneAuthOTPVerified(phoneNumber: phoneNumber, otpCode: token));
      } else {
        emit(PhoneAuthOTPNotVerified(
            message: 'کد وارد شده صحیح نیست', otpCode: token,phoneNumber: phoneNumber));
      }
    } catch (error) {
      emit(phoneAuthFailedState);
    }
  }

  Future<void> sendResetPasswordOtp(String phoneNumber) async {
    emit(AuthLoading());
    try {
      await _sendResetPasswordOtpUsecase(phoneNumber);
      emit(PhoneAuthOTPSent(phoneNumber: phoneNumber));
    } on ResetPasswordException catch (e) {
      emit(ResetPasswordExceptionState(message: e.message));
    } catch (e) {
      emit(phoneAuthFailedState);
    }
  }
}

Solution

  • This is opinon-based... but I would say that yes it is, or at least can be, OK to store the phoneNumber in the AuthCubit. It depends on how AuthCubit is created with respect to phoneNumber.

    If AuthCubit can exist without phoneNumber, and then phoneNumber is set at a later time, then you should let AuthState carry state(s) that reflect that phoneNumber is either set or not.

    But if AuthCubit is never created, and can never be created without a phoneNumber present, then you can add phoneNumber as a final parameter to the AuthCubit class.