skip to Main Content

im new with bloc i already read the documentation and its well documented so it’s not hard to understand it but it’s different in practical. I wonder if there is any better approach to add, update, delete with bloc like this?

   class TodoBloc extends Bloc<TodoEvent, TodoState> {
  TodoBloc() : super(TodoState(todos: const [])) {
    on<TodoEventAdd>(
      (event, emit) {
        emit(
          state.copyWith(
            todos: [...state.todos, event.todo],
          ),
        );
      },
    );

    on<TodoEventDelete>(
      (event, emit) {
        List<TodoModel> _todos = [...state.todos];

        _todos.removeWhere((TodoModel todo) => todo.id == event.todo.id);

        emit(
          state.copyWith(
            todos: _todos,
          ),
        );
      },
    );

    on<TodoEventIsCompleted>(
      (event, emit) {
        List<TodoModel> _todos = [...state.todos];

        final newTodo = _todos
            .elementAt(event.index)
            .copyWith(isCompleted: event.isCompleted);

        _todos[event.index] = newTodo;

        emit(
          state.copyWith(
            todos: _todos,
          ),
        );
      },
    );
  }
}

2

Answers


  1. You can do it like this,

    Your code will look good and will be readable and testable in this way.

      class TodoBloc extends Bloc<TodoEvent, TodoState> {
    TodoBloc() : super(TodoState(todos: const [])) {
    on<TodoEventAdd>((event, emit) => addTodo(event,emit));
    on<TodoEventDelete>((event, emit) => deleteTodo(event,emit));
    on<TodoEventIsCompleted>((event, emit)=> todoCompleted(event,emit));
    }
    
    void addTodo(TodoEventAdd event, Emitter emit){
    emit(
          state.copyWith(
            todos: [...state.todos, event.todo],
          ),
        );
    } 
    
    void deleteTodo(TodoEventDelete event, Emitter emit){
    List<TodoModel> _todos = [...state.todos];
    
        _todos.removeWhere((TodoModel todo) => todo.id == event.todo.id);
    
        emit(
          state.copyWith(
            todos: _todos,
          ),
        );
    }
    
    void todoCompleted(TodoEventIsCompleted event,Emitter emit){
    List<TodoModel> _todos = [...state.todos];
    
        final newTodo = _todos
            .elementAt(event.index)
            .copyWith(isCompleted: event.isCompleted);
    
        _todos[event.index] = newTodo;
    
        emit(
          state.copyWith(
            todos: _todos,
          ),
        );
     }  
     }
    
    Login or Signup to reply.
  2. don’t think there is a better approach to accomplish this; it works perfectly in the ideal flow.

    However, have you heard of Cubit? If not, I recommend checking out a good article on it. Cubit can simplify your code by reducing the need for event classes. It functions similarly to Bloc and works seamlessly with the same Widgets (BlocProvider, BlocConsumer, BlocBuilder, and BlocListener) while providing the same functionality. The key difference is that Cubit doesn’t require you to define events. Instead, you define class functions for different actions (such as add, update, and delete), and these functions emit states that automatically update your UI accordingly.

    Below i’m putting code for cubit corrosponding to your bloc code:

    import 'package:flutter_bloc/flutter_bloc.dart';
    
    class TodoCubit extends Cubit<TodoState> {
      TodoCubit() : super(TodoState(todos: const []));
    
      void addTodo(TodoModel todo) {
        final updatedTodos = [...state.todos, todo];
        emit(state.copyWith(todos: updatedTodos));
      }
    
      void deleteTodo(TodoModel todo) {
        final updatedTodos = List<TodoModel>.from(state.todos);
        updatedTodos.removeWhere((element) => element.id == todo.id);
        emit(state.copyWith(todos: updatedTodos));
      }
    
      void updateTodoIsCompleted(int index, bool isCompleted) {
        final updatedTodos = List<TodoModel>.from(state.todos);
        final updatedTodo = updatedTodos[index].copyWith(isCompleted: isCompleted);
        updatedTodos[index] = updatedTodo;
        emit(state.copyWith(todos: updatedTodos));
      }
    }
    

    Here i have just used a single state TodoState as you have did in the bloc, but i don’t recommend that, you should have different state to handle things like a state to handle error TodoErrorState and other. TodoLoadedState etc..

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search