Issue
Stream<SignInFormState> _performActionOnAuthFacadeWithEmailAndPassword(
Future<Either<AuthFailure, Unit>> Function({
@required EmailAddress emailAddress,
@required Password password,
})
forwardedCall,
) async* {
Either<AuthFailure, Unit> failureOrSuccess;
final isEmailValid = state.emailAddress.isValid();
final isPasswordValid = state.password.isValid();
if (isEmailValid && isPasswordValid) {
yield state.copyWith(
isSubmitting: true,
authFailureOrSuccessOption: none(),
);
failureOrSuccess = await forwardedCall(
emailAddress: state.emailAddress,
password: state.password,
);
}
yield state.copyWith(
isSubmitting: false,
showErrorMessages: true,
authFailureOrSuccessOption: optionOf(failureOrSuccess),
);
}
This worked fine in Resocoder’s DDD tutorial But ever since the Flutter’s NNBD, we are required to add the late keyword in
Either<AuthFailure, Unit> failureOrSuccess;
and so it changes to:
late Either<AuthFailure, Unit> failureOrSuccess;
Now the error in the:
yield state.copyWith(
isSubmitting: false,
showErrorMessages: true,
authFailureOrSuccessOption: optionOf(failureOrSuccess),
);
goes away since we added the late keyword.
However, we get the following error when we test out the email address validation in the form. So instead of getting a red alert in TextFormField we get the following error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Unhandled error
LateInitializationError: Local 'failureOrSuccess' has not been initialized. occurred in
Instance of 'SignInFormBloc'.
Removing the late keyword in the Either<AuthFailure, Unit> failureOrSuccess; throws the same error again, due to null-safety being defaulted in Flutter SDK.
I tried degrading flutter and many more things but there seems to be no workaround.
Can anyone help?
Solution
Okay so found the answer to the problem just replace the following code:
Stream<SignInFormState> _performActionOnAuthFacadeWithEmailAndPassword(
Future<Either<AuthFailure, Unit>> Function({
@required EmailAddress emailAddress,
@required Password password,
})
forwardedCall,
) async* {
Either<AuthFailure, Unit> failureOrSuccess;
final isEmailValid = state.emailAddress.isValid();
final isPasswordValid = state.password.isValid();
if (isEmailValid && isPasswordValid) {
yield state.copyWith(
isSubmitting: true,
authFailureOrSuccessOption: none(),
);
failureOrSuccess = await forwardedCall(
emailAddress: state.emailAddress,
password: state.password,
);
}
yield state.copyWith(
isSubmitting: false,
showErrorMessages: true,
authFailureOrSuccessOption: optionOf(failureOrSuccess),
);
}
with:
Stream<SignInFormState> _performActionOnAuthFacadeWithEmailAndPassword(
Future<Either<AuthFailure, Unit>> Function({
required EmailAddress emailAddress,
required Password password,
})
forwardedCall,
) async* {
Either<AuthFailure, Unit> failureOrSuccess;
final isEmailValid = state.emailAddress.isValid();
final isPasswordValid = state.password.isValid();
if (isEmailValid && isPasswordValid) {
yield state.copyWith(
isSubmitting: true,
authFailureOrSuccessOption: none(),
);
failureOrSuccess = await forwardedCall(
emailAddress: state.emailAddress,
password: state.password,
);
yield state.copyWith(
isSubmitting: false,
showErrorMessages: AutovalidateMode.always,
authFailureOrSuccessOption: optionOf(failureOrSuccess),
);
} else {
yield state.copyWith(
isSubmitting: false,
showErrorMessages: AutovalidateMode.always,
authFailureOrSuccessOption: none(),
);
}
}
here you won’t require the late keyword as the if-else condition is calling the failureOrSuccess variable and so in every case, failureOrSuccess is getting some value, in else condition it is none(). The code works fine for now, as we still get the red alerts in the Form UI when we try to make an invalid signin.
I will update my answer in case I find a better alternative.
PS: My environment in pubspec.yaml file:
environment:
sdk: ">=2.12.0 <3.0.0"
Answered By – Somanshu Singh
Answer Checked By – Candace Johnson (FlutterFixes Volunteer)