Why when i use a class in dart with equatable and just a list as property the copyWith method return the same object, same hascode

Viewed 948

Im using bloc and it was working as expected but today i notice a strage behaviour when i was sending the same state (RefreshState) using copyWith, the state wasnt trigger after second call. then i did a test creating two objects and compared them but the result was they are the same object, very odd.

So why is this happen?, this is my class:

 class Model extends Equatable {
  final List<Product> mostBuyProducts;

  const Model({
    this.mostBuyProducts,
  });

  Model copyWith({
    List<Product> mostBuyProducts,
  }) =>
      Model(
        mostBuyProducts: mostBuyProducts ?? this.mostBuyProducts,
      );

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

and then i use the CopyWith method like (inside the bloc):

  Stream<State> _onDeleteProduct(OnDeleteProduct event) async* {
    state.model.mostBuyProducts.removeWhere((p) => p.id == event.id);

    var newMostBuyProducts = List<Product>.from(state.model.mostBuyProducts);

    final model1 = state.model;
    final model2 = state.model.copyWith(mostBuyProducts: newMostBuyProducts);

    final isEqual = (model1 == model2);

    yield RefreshState(
        state.model.copyWith(mostBuyProducts: newMostBuyProducts));
  }

isEqual return true :/

BTW this is my state class

@immutable
abstract class State extends Equatable {
  final Model model;
  State(this.model);

  @override
  List<Object> get props => [model];
}
1 Answers

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/

Using one such method in the solution below! Just change the copyWith method with the one below.

Model copyWith({
    List<Product> mostBuyProducts,
  }) =>
      Model(
        mostBuyProducts: mostBuyProducts ?? [...this.mostBuyProducts],
      );
Related