Abdullah Khan
Abdullah Khan

Reputation: 1481

Flutter bloc state does not update state when updating List/array index

I'm trying to implement checkbox logic in bloc class. For that I create List<bool> checked in bloc class code is below. When CheckBoxClicked event trigger then for the first time state updated and I can see the box checked.

class CartProductsListBloc
    extends Bloc<CartProductsListEvent, CartProductsListState> {
  CartProductsListBloc() : super(InitialCartProductsListState());

  final ProductRepository productRepository = ProductRepository();
  List<bool> checked = List<bool>();
  var productsList;

  @override
  Stream<CartProductsListState> mapEventToState(
      CartProductsListEvent event) async* {
    if (event is FetchCartProductsList) {
      yield FetchingInProgress();
      try {
        productsList = await productRepository.loadListOfProductInUserCart();
        //initialize checked according to productsList
        for (int i = 0; i < productsList.length; i++) {
          checked.add(false);
        }
        yield FetchCartProductsListSuccess(
            productsList: productsList, checked: checked);
      } catch (error) {
        yield FetchCartProductsListFail(
            error: 'Fail to laod data. Please try again\nOr Report the issue');
      }
    }
    if (event is CheckBoxClicked) {
      checked[event.index] = !checked[event.index];
      yield CheckedBoxClickedHappened(
          productsList: productsList, checked: checked);
    }
  }
}

But after that no matter how many times the event CheckBoxClicked called the state UI does not update. When I hot refresh, the changes appear which means logic works fine but the problem is Equatable is not able to detect changes in List/array index. Following is the code of CheckedBoxClickedHappened state.

class CheckedBoxClickedHappened extends CartProductsListState {
  final productsList;
  final checked;
  const CheckedBoxClickedHappened({@required this.productsList, @required this.checked});

  @override
  List<Object> get props => [productsList, checked];
}

Note: I fixed the issue by adding the int count = 0; in bloc class and on each time when CheckBoxClicked event triggered I update the count++ like below

if (event is CheckBoxClicked) {
          checked[event.index] = !checked[event.index];
          yield CheckedBoxClickedHappened(
              productsList: productsList, checked: checked, count: count++);
        }

and in state

@override
      List<Object> get props => [productsList, checked, count];

The purpose of the question is to know, does the Equatable can't detect changes in List index or I'm doing something wrong? If there is any confusion in question please ask I will improve it.

Upvotes: 9

Views: 1400

Answers (2)

Guney Ozsan
Guney Ozsan

Reputation: 330

Even if you change a list item, it is still the same list. You may:

  • Create a new List each time one of the list items is updated (Using .toList() works for most cases),
  • Try using List.unmodifiable
  • Try using BuiltList from built_collection.

Upvotes: 0

Abuzar Rasool
Abuzar Rasool

Reputation: 87

Yes because lists are mutable. In order to detect a change in the list you need to make a deep copy of the list some methods to make a deep copy are available here : https://www.kindacode.com/article/how-to-clone-a-list-or-map-in-dart-and-flutter/

Upvotes: 0

Related Questions