Flutter bloc migration due to mapEventToState is not working
Asked Answered
B

2

6

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();
    }
  }
...
Bludgeon answered 1/1, 2022 at 14:15 Comment(2)
Looks correct to me. How exactly isn't it working? Maybe also add some code for mapSignInWithGoogleToStateGiguere
I have added itBludgeon
G
12

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

Giguere answered 1/1, 2022 at 15:30 Comment(1)
How's it possible to call emit multiple times? I get an error and created another question here #77253745Taxi
D
1

The getter does not belong in the constructor body and I guess it isn't really needed anymore. You could solve the problem like this:

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

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

  Future<void> _handleSignInWithGoogleEvent(
      SignInWithGoogle event,
      Emitter<SignInState> emit,
  ) async {
    // TODO do your thing and create and emit the SignInWithGoogleState
    emit(SignInWithGoogleState());
  }
}

Be careful, the events in bloc v8 are not handled sequentially anymore, but concurrently. Give this blog post a read: https://verygood.ventures/blog/how-to-use-bloc-with-streams-and-concurrency

Dishrag answered 1/1, 2022 at 15:6 Comment(1)
Hi, I appreciate your comment. I also updated my code above showing the mapSignInWithGoogleToState(). I will also take a look on your link provided.Bludgeon

© 2022 - 2024 — McMap. All rights reserved.