Search code examples
flutterdartblocdartz

Flutter bloc 8 some error in Either / fold return with async


I am migrating my project to the new version of Flutter and I use the BloC package. As you know Bloc has been updated and it has changed most of its code, so now I am adapting mine, but I have some bugs.

The argument type 'Future Function(bool)' can't be assigned to the parameter type 'UserState Function(bool)

The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.

Before :

  Stream<UserState> _validate(ValidateEvent event) async* {

    final successOrFailure = await services.validate();
    
    yield* successOrFailure.fold(
      (sucess) async* {
        final session = await services.getSession();
        yield* session.fold(
          (session) async* {
            yield UserSuccess(session);

            yield UserLogged(session);
          },
          (failure) async* {
            yield UserError(failure.message);
          },
        );
      },
      (failure) async* {
        yield UserError(failure.message);
      },
    );
  }

After :

UserBloc({this.services}) : super(UserInitial()) {
    on<ValidateEvent>(_onValidate);
  }

void _onValidate(
    ValidateEvent event,
    Emitter<UserState> emit,
  ) async {

    final successOrFailure = await services.validate();
    
    emit(
      successOrFailure.fold(
        (success) async {
          final session = await services.getSession();
          emit(
            session.fold(
              (session) { // ! The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
                emit(UserSuccess(session));

                emit(UserLogged(session));
              },
              (failure) { // ! The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
                emit(UserError(failure.message));
              },
            ),
          );
        }, // ! The argument type 'Future<Null> Function(bool)' can't be assigned to the parameter type 'UserState Function(bool)
        (failure) { // ! The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
          emit(UserError(failure.message));
        },
      ),
    );
  }

I need to have that async inside because I call the service again, and about the body, it seems to me that I have to return it somehow but I have some logic inside and I don't know how to do it.


Solution

  • The only things you can emit are instances of your state type, in this case UserState. Instead of trying to emit a Future, you should await it instead.

    void _onValidate(
        ValidateEvent event,
        Emitter<UserState> emit,
      ) async {
    
        final successOrFailure = await services.validate();
        
        await successOrFailure.fold( // This will return FutureOr<Null>
          (success) async {
            final session = await services.getSession();
            session.fold( // This isn't asynchronous, so no need to await here
              (session) {
                emit(UserSuccess(session));
    
                emit(UserLogged(session));
              },
              (failure) {
                emit(UserError(failure.message));
              },
            );
          },
          (failure) {
            emit(UserError(failure.message));
          },
        );
      }