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();
}
}
...
CodePudding user response:
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 informations as to "why?": https://bloclibrary.dev/#/migration?id=rationale-6
CodePudding user response:
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