ResoCoder / finished-flutter-firebase-ddd-course

https://resocoder.com/flutter-firebase-ddd-course
GNU General Public License v3.0
396 stars 115 forks source link

Error with copyWith in sign_in_form_bloc.dart #11

Open Daniel203 opened 4 years ago

Daniel203 commented 4 years ago

The copyWith() method doesn't work inside sign_in_form_bloc.dart. The state doesn't change when the user types the email or password inside the UI form. The event is properly working and contains the changed value, but I can't add this value to the state. The state remains in initial form even after the copyWith().

Annotazione 2020-04-30 112620

ResoDev commented 4 years ago

Hello! This is extremely strange because copyWith is implemented by freezed code gen and it has always worked for me. Does it still happen even after you regenerate code by running flutter pub run build_runner build --delete-conflicting-outputs?

Daniel203 commented 4 years ago

Thanks for your answer. Yes, I've already executed the command. I've also tried changing the freezed version, using both the one present in your project and the latest version. The strange thing is that if I try to print state.copyWith( ... ), in the console I can see the status updated with the data present in the event, but despite this, the bloc status doesn't change. I really don't know what the problem could be.

yakou32 commented 4 years ago

I also had a similar problem.

Thing is that the generated file causes issues with copyWith(...)

The only workaround I found so far was to use the exact generated version from Matej's repo instead of the one generated locally...

Le lun. 4 mai 2020 à 21:44, Daniel Arduini notifications@github.com a écrit :

Thanks for your answer. Yes, I've already executed the command. I've also tried changing the freezed version, using both the one present in your project and the latest version. The strange thing is that if I try to print state.copyWith( ... ), in the console I can see the status updated with the data present in the event, but despite this, the bloc status doesn't change. I really don't know what the problem could be.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ResoCoder/finished-flutter-firebase-ddd-course/issues/11#issuecomment-623666895, or unsubscribe https://github.com/notifications/unsubscribe-auth/AATA2SPRXMB5ISNLUQOL3XLRP4LJLANCNFSM4MVK5TWA .

darozarena commented 4 years ago

Hello! Same problem here... I have also another error when starting the app and calling SignInFormState.initial() with EmailAddress('') and Password(''). Both value objects try to execute the validation of the input and return Left(...). Here is the stacktrace:

I/flutter ( 9950): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 9950): The following Left<ValueFailure<dynamic>, dynamic> object was thrown building
I/flutter ( 9950): BlocConsumer<SignInFormBloc, SignInFormState>(dirty):
I/flutter ( 9950):   Left(ValueFailure<dynamic>.invalidEmail(failedValue: ))
I/flutter ( 9950):
I/flutter ( 9950): The relevant error-causing widget was:
I/flutter ( 9950):   BlocConsumer<SignInFormBloc, SignInFormState>
darozarena commented 4 years ago

Hello! Same problem here... I have also another error when starting the app and calling SignInFormState.initial() with EmailAddress('') and Password(''). Both value objects try to execute the validation of the input and return Left(...). Here is the stacktrace:

I/flutter ( 9950): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 9950): The following Left<ValueFailure<dynamic>, dynamic> object was thrown building
I/flutter ( 9950): BlocConsumer<SignInFormBloc, SignInFormState>(dirty):
I/flutter ( 9950):   Left(ValueFailure<dynamic>.invalidEmail(failedValue: ))
I/flutter ( 9950):
I/flutter ( 9950): The relevant error-causing widget was:
I/flutter ( 9950):   BlocConsumer<SignInFormBloc, SignInFormState>

I found my error. I was throwing left(...) in value_validators.dart instead of return it 😅

Daniel203 commented 4 years ago

Trying to follow this example (https://github.com/felangel/bloc/tree/master/examples/flutter_login), I finally found the cause of the problem. Problems are EmailAddress and Password classes inside the bloc state. I've seen that replacing them with String, the copyWith() method works correctly.

Then I had to add two more parameters (isEmailValid, isPasswordValid) to the state that check if the data are valid. The way I check if a data is valid is not very nice. It would have been better to create methods that check the data directly inside sign_in_form_bloc.dart but to reuse the code and keep it as close as possible to the initial project, I did it this way.

This is my solution. (I know this isn't the right solution, but it's more like a temporary fix.)

sign_in_form_state.dart

part of 'sign_in_form_bloc.dart';

@freezed
abstract class SignInFormState with _$SignInFormState {
  const factory SignInFormState({
    @required String emailAddress,
    @required String password,
    @required bool isEmailValid,
    @required bool isPasswordValid,
    @required bool showErrorMessage,
    @required bool isSubmitting,
    @required Option<Either<AuthFailure, Unit>> authFailureOrSuccessOption, 
  }) = _SignInFormState;

  factory SignInFormState.initial() => SignInFormState(
    emailAddress: '',
    password: '',
    isEmailValid: false,
    isPasswordValid: false,
    showErrorMessage: false,
    isSubmitting: false,
    authFailureOrSuccessOption: none(),
  );
}

sign_in_form_bloc.dart

...
@override
  Stream<SignInFormState> mapEventToState(
    SignInFormEvent event,
  ) async* {
    yield* event.map(
      emailChanged: (e) async* {
        yield state.copyWith(
          emailAddress: e.emailStr,
          isEmailValid: EmailAddress(e.emailStr).isValid(),
          authFailureOrSuccessOption: none(),
        );
      }, 
      passwordChanged: (e) async* {
        yield state.copyWith(
          password: e.passwordStr,
          isPasswordValid: Password(e.passwordStr).isValid(),
          authFailureOrSuccessOption: none(),
        );
      },
...
TezzaMichael commented 4 years ago

danke @Daniel203