flutterbloc

Flutter bloc migration due to mapEventToState is not working


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();
    }
  }
...

Solution

  • 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/#rationale-8