5

My Bloc state isn't updating and I've found the problem to potentially be a Map<String, Map<String, String> property that isnt being compared properly. Please correct me if I'm wrong, but the state updates when the other properties change, just not when the imageUrls property updates.

These are my state objects

abstract class PropertiesState extends Equatable {
  const PropertiesState();
}

class PropertiesLoaded extends PropertiesState {
  final int count;
  final List<Property> properties;
  final Map<String, Map<String, String>> imageUrls;

  const PropertiesLoaded({
    this.count,
    this.properties,
    this.imageUrls,
  });

  @override
  List<Object> get props => [count, properties, imageUrls];
}

The imageUrls field can have any string key/value pairs. I haven't been able to find any information on how I should do this.

Thanks for the help!

Dustin Silk
  • 4,320
  • 5
  • 32
  • 48
  • I think it should work well, however, change Map> to dynamic, just as a test, Tell me the result – farouk osama Jul 14 '20 at 13:37
  • 1
    You're right it does work. Maps compare easily. Turns out I was changing a property on the imageUrl instead of creating a new map with each event. I get why properties on classes need to be immutable for equatable to work now too – Dustin Silk Jul 14 '20 at 14:03

2 Answers2

6

Because Equatable is trying to compare the reference of your List or Map object because they are not primitive type like int. You can try deep copy a Map object (using Map.from()) and replace the old one, and use hash code to do the comparison.

Liu Junhan
  • 203
  • 3
  • 8
6

From Docs

Equatable properties should always be copied rather than modified. If an Equatable class contains a List or Map as properties, be sure to use List.from or Map.from respectively to ensure that equality is evaluated based on the values of the properties rather than the reference.

emit(PropertiesLoaded(count, properties,
Map<String, Map<String, String>>.from(imageUrls)));
Eslam Ashraf
  • 316
  • 3
  • 7