skip to Main Content

So I have a Flutter app with Bloc for state mangement. I want to keep a list of users in Bloc so I can access it from different places in the app. But as it is now I pass this list of users to every state. Can I somehow avoid this boilerplate code?

Here is an example of my Bloc State:

@immutable
abstract class UsersState {
  final List<User> users;
  final User? user;

  const UsersState({required this.users, required this.user});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List<User> users = const [], User? user})
      : super(users: users, user: user);
}


class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List<User> users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

In this example I don’t want to have to pass list of users to FriendAddedState.
And here is how it looks in Bloc:

 else if (event is AddFriend) {
        emit(FriendAddPending(users: users, user: user));
        final result = await usecases.addFriend(event.friendId);
        result.fold((error) {
          emit(UsersErrorState(
              users: users, user: user, message: error.message));
        }, (success) {
          user = success;
          emit(FriendAddedState(users: users, user: user));
        });
      } 

4

Answers


  1. You could use:
    context.read<YourBlocClass>();
    or
    BlocProvider.of<YourBlocClass>(context);
    Hope this helps.

    Login or Signup to reply.
  2. You could try to use a two different blocs, one for the state, one for the list of users.

    An alternative can be to have just one state class with an enum for all the possible states.
    This way you don’t reinitialize the class every state change. Something like:

    enum UserState {Initial, Loaded, Pending..}
    
    class UsersState {
      UserState? state;
      List<User> users;
      User? user;
    
      const UsersState({required this.users, required this.user});
    }
    
    Login or Signup to reply.
  3. You don’t have to define users and user in UserState if you don’t need them in all the bloc states. You could just define them in UsersLoadedState FriendAddedState like this:

    
    @immutable
    abstract class UsersState {
      const UsersState();
    }
    
    class UsersInitial extends UsersState {
      const UsersInitial();
    }
    
    class UsersLoadedState extends UsersState {
      const UsersLoadedState({
        required this.users,
        required this.user,
      });
    
      final List<User> users;
      final User? user;
    }
    
    class UsersPendingState extends UsersState {
      const UsersPendingState();
    }
    
    class UsersErrorState extends UsersState {
      final String message;
    
      const UsersErrorState({required this.message});
    }
    
    class FriendAddedState extends UsersState {
      const FriendAddedState({
        required this.users,
        required this.user,
      });
    
      final List<User> users;
      final User? user;
    }
    

    [Recommended] if you want to access user in every state of bloc, you can use a single class for your bloc state and an enum to define its state:

    @immutable
    class UsersState {
      final List<User> users;
      final User? user;
      final String? message;
      final UserStatus status;
    
      const UsersState({
        required this.status,
        required this.users,
        this.user,
        this.message,
      });
    
      const UsersState.initial()
          : status = UserStatus.initial,
            users = const [],
            user = null,
            message = null;
    
      UsersState copyWith(
        List<User>? users,
        User? user,
        String? message,
        UserStatus? status,
      ) {
        return UsersState(
          status: status ?? this.status,
          users: users ?? this.users,
          message: message ?? this.message,
          user: user ?? this.user,
        );
      }
    }
    
    enum UserStatus {
      initial,
      loaded,
      pending,
      error,
      friendAdded,
    }
    

    then in your bloc class, anywhere you wanted to emit new state, use state.copyWith()!

    Login or Signup to reply.
  4. You can make users optional so that they are not required in every state.

    Without null safety

    @immutable
    abstract class UsersState {
      final List<User>? users;
      final User? user;
    
      const UsersState({required this.users, this.user});
    }
    
    class UsersInitial extends UsersState {
      UsersInitial() : super(users: [], user: null);
    }
    
    class UsersLoadedState extends UsersState {
      const UsersLoadedState({required List<User> users, required User? user})
          : super(users: users, user: user);
    }
    
    class UsersPendingState extends UsersState {
      const UsersPendingState({List<User> users = const [], User? user})
          : super(users: users, user: user);
    }
    
    
    class UsersErrorState extends UsersState {
      final String message;
      const UsersErrorState(
          {required List<User> users, required User? user, required this.message})
          : super(users: users, user: user);
    }
    
    class FriendAddedState extends UsersState {
      const FriendAddedState({required User? user})
          : super(user: user);
    }
    

    With null safety

    @immutable
    abstract class UsersState {
      final List<User>? users;
      final User? user;
    
      const UsersState({required this.users, this.user=[]});
    }
    
    class UsersInitial extends UsersState {
      UsersInitial() : super(users: [], user: null);
    }
    
    class UsersLoadedState extends UsersState {
      const UsersLoadedState({required List<User> users, required User? user})
          : super(users: users, user: user);
    }
    
    class UsersPendingState extends UsersState {
      const UsersPendingState({List<User> users = const [], User? user})
          : super(users: users, user: user);
    }
    
    
    class UsersErrorState extends UsersState {
      final String message;
      const UsersErrorState(
          {required List<User> users, required User? user, required this.message})
          : super(users: users, user: user);
    }
    
    class FriendAddedState extends UsersState {
      const FriendAddedState({required User? user})
          : super(user: user);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search