Home > Net >  Flutter Either fold is skipped
Flutter Either fold is skipped

Time:09-15

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!

CodePudding user response:

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.

CodePudding user response:

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

  • Related