简体   繁体   中英

Flutter Either fold is skipped

I'm working on a small app with GoogleSignIn-Auth. and stumbled upon a bug I cannot wrap my head around.

It seems like the fold of an Either seems to be skipped. It used to work before, when I had a complicated pile of blocs. Since I started reorganizing my widgets it started to this.

Future<Either<Failure, SignUpSuccess>> signInWithGoogle() async {
try {
  final signUpSuccess = await googleRemoteDataSource.signInWithGoogle();

  signUpSuccess.fold(
      (failure) => () {
            print("Got failure!");
            return Left(GeneralFailure());
          },
      (success) => () {
            return Right(signUpSuccess);
          });

  print("I skipped the fold!");
} catch (e) {
  print("Caught exception!");
  return Left(GeneralFailure());
}

print("Instant fail!");
return Left(GeneralFailure());
}

I have a widget that's listening to a SignInBloc emitting the states:

class SignUpRoot extends StatelessWidget {
  SignUpRoot({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: BlocProvider(
            create: (context) => sl<SignInBloc>(),
            child: BlocListener<SignInBloc, SignInState>(
              listener: (context, state) {
                if (state is SignInWithGoogleLoaded) {
                  // Navigate to SignInNamePage
                  print("This seems to work!");
                } else if (state is SignInWithGoogleLoading) {
                  // Navigate to loading page
                  print("Loading Google...");
                } else if (state is SignInError) {
                  // Navigate to error page
                  print("An error occured while signing in!");
                }
              },
              child: const SignUpMainPage(),
            )));
  }

And last but not least my bloc:

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final SignUpUseCases useCases;
  SignInBloc({required this.useCases}) : super(SignInInitial()) {
    on<SignInWithGooglePressed>((event, emit) async {
      // Show Loading indicator
      emit(SignInWithGoogleLoading());

      // wait for sign in response
      Either<Failure, SignUpSuccess> successOrFailure =
          await useCases.signInWithGoogle();

      // emit corresponding state
      successOrFailure.fold(
          (failure) => emit(SignInError()),
          (success) => () {
                // emit sign in loaded state
                emit(SignInWithGoogleLoaded());
                // create new (local) user

                // assign user data e.g. display name
              });
    });
  }
}

Thanks for any help!

The problem is that the fold method returns the value of the left or right functions.

https://pub.dev/documentation/dartz/latest/dartz/Either/fold.html

B fold<B>(
  B ifLeft(
   L l
  ),
  B ifRight(
   R r
  )
)

Your code should be corrected to:

Future<Either<Failure, SignUpSuccess>> signInWithGoogle() async {
  try {
    final signUpSuccess = await googleRemoteDataSource.signInWithGoogle();

    return signUpSuccess.fold(
      (failure) => () {
            return Left(GeneralFailure());
          },
      (success) => () {
            return Right(signUpSuccess);
          });
  } catch (e) {
    return Left(GeneralFailure());
  }
  return Left(GeneralFailure());
}

I just added the return at the start of the fold, now the value returned from left or right will be returned by your function.

You just have to remove the arrow in the success part of the fold .

 Future<Either<Failure, SignUpSuccess>> signInWithGoogle() async { try { final signUpSuccess = await googleRemoteDataSource.signInWithGoogle(); signUpSuccess.fold( (failure) => () { print("Got failure;"); return Left(GeneralFailure()), }; (success){ return Right(signUpSuccess); }); print("I skipped the fold;"); } catch (e) { print("Caught exception;"); return Left(GeneralFailure()); } print("Instant fail!"); return Left(GeneralFailure()); }
 class SignInBloc extends Bloc<SignInEvent, SignInState> { final SignUpUseCases useCases; SignInBloc({required this.useCases}): super(SignInInitial()) { on<SignInWithGooglePressed>((event, emit) async { // Show Loading indicator emit(SignInWithGoogleLoading()); // wait for sign in response Either<Failure, SignUpSuccess> successOrFailure = await useCases.signInWithGoogle(); // emit corresponding state successOrFailure.fold( (failure) => emit(SignInError()), (success) { emit(SignInWithGoogleLoaded()); }); }); } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM