How to solve: Flutter bloc migration due to mapEventToState is not working

Question

Asked by Mr. T on January 01, 2022 (source).

I am following the migration to the new bloc 8.0.0. I am trying to remove the mapEventToState but I am having a difficulty in doing so. Can you help me how to do it. I have tried it below but it won't work.

Old code:

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc(
      {required this.authenticationRepository,
      required this.userDataRepository})
      : super(SignInInitialState());

  SignInState get initialState => SignInInitialState();

  @override
  Stream<SignInState> mapEventToState(
    SignInEvent event,
  ) async* {
    if (event is SignInWithGoogle) {
      yield* mapSignInWithGoogleToState();
    }
  }

Stream<SignInState> mapSignInWithGoogleToState() async* {
    yield SignInWithGoogleInProgressState();
    try {
      String res = await authenticationRepository.signInWithGoogle();
      yield SignInWithGoogleCompletedState(res);
    } catch (e) {
      print(e);
      yield SignInWithGoogleFailedState();
    }
  }
...

Migration code (does not work):

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc(
      {required this.authenticationRepository,
        required this.userDataRepository})
      : super(SignInInitialState())
  {
    SignInState get initialState => SignInInitialState();

    on<SignInWithGoogle>((event, emit) => emit(mapSignInWithGoogleToState()));
  }

Stream<SignInState> mapSignInWithGoogleToState() async* {
    yield SignInWithGoogleInProgressState();
    try {
      String res = await authenticationRepository.signInWithGoogle();
      yield SignInWithGoogleCompletedState(res);
    } catch (e) {
      print(e);
      yield SignInWithGoogleFailedState();
    }
  }
...

Answer

Question answered by puelo (source).

Your issue is that mapSignInWithGoogleToState() is returning a Stream of States, but the new structure needs explicit invocations of emit each time a new state needs to be emitted.

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc({required this.authenticationRepository,
    required this.userDataRepository})
      : super(SignInInitialState()) {
    on<SignInWithGoogle>(mapSignInWithGoogleToState);
  }

  Future<void> mapSignInWithGoogleToState(
      SignInWithGoogle event,
      Emitter<SignInState> emit,
  ) async {
    emit(SignInWithGoogleInProgressState());
    try {
      String res = await authenticationRepository.signInWithGoogle();
      emit(SignInWithGoogleCompletedState(res));
    } catch (e) {
      print(e);
      emit(SignInWithGoogleFailedState());
    }
  }
}

Here is some more information as to "why?": https://bloclibrary.dev/#/migration?id=rationale-6

BLOC FLUTTER
SHARE: