0
votes

I'm trying to make a authentication screen with the BLoC pattern, but I have doubts about best practices even after reading the documentation of the flutter_bloc lib and reading multiple implementations.

The main problem I have is about state management. My authentication screen should handle the following states:

  • Password visible or not.
  • Show register or login screen.
  • TextEdit validation.
  • Loading (waiting for a Firebase response).
  • if authenticated, show home. Else show the authentication page

I really wanted to do all the logic in blocs to make a clean architecture. Some people say they use a bloc per screen, sometime a bloc for the whole app, but flutter_bloc library says you should use a bloc for any widget complex enough.

My problem is, how can I deal with multiple states?

  • If I store variables in states classes extended from the mother AuthState class, I can't access it in mapEventToState because the block receives the mother just the AuthState class.
  • I tried handling all states in the same bloc by passing the current state in a event (as I will show in the code below), but then I can't properly set the initial state.

What's the best practice solution?

  • Passing all state classes as variables in the mother AuthState class? Then I could persist data using "state.passwordFieldState". But I never saw something like that. I bet it's a wrong approach.
  • Create a model to store the state and manipulate the model when a change event enter the bloc?
  • Creating multiple blocs or cubits? One cubit for authentication, 1 cubit for password visibility, one bloc for authentication handling? My concern with that would be nesting bloc builders.
  • Or should I forget about blocs for simple things and use providers instead? I wouldn't like to do that because it can lead to spaghetti code.

Here's my code:

class AuthState extends Equatable{
  @override

  List<Object> get props => [];
}

class PasswordFieldState extends AuthState{
  final bool isObscured;
  PasswordFieldState({this.isObscured});
  @override
  List<Object> get props => [isObscured];
}

class AuthEvent extends Equatable{
  @override
  List<Object> get props => [];
}

class SetObscurePassword extends AuthEvent{
  bool isObscured = false;
}

class passwordTextEditChanged extends AuthEvent{}

class emailTextEditChanged extends AuthEvent{}

class AuthBloc extends Bloc<AuthEvent,AuthState> {

  AuthBloc(AuthState initialState) : super(initialState);

  @override
  Stream<AuthState> mapEventToState(AuthEvent event) async* {
    if (event is SetObscurePassword) {
      yield PasswordFieldState(isObscured: !event.isObscured);
    } else if (event is passwordTextEditChanged) {
      print("validation handling");
    } else if (event is emailTextEditChanged) {
      print("validation handling");
    }
  }
1

1 Answers

0
votes

I think I found the answer.

It's not possible to make a bloc for the entire application using the flutter_bloc library. It's only possible to do such thing using stream controllers to create a bloc without the library.

But it's not a bad thing to create a bloc for each different task. It makes the code more testable and easier to understand.