flutterdartblocflutter-cubit

state is not being emited properly


As the title implies emit isn't working properly so I created a basic app counter but a bit detailed so when the user click the increment button it supposed to trigger the state to be updated with the new state but this happens only in the first time (only one element is added to the map which is the first store the user entered and clicked on an increment button of a product) what supposed to happen is that each store has its own cart so when user enters a store and click on the button immediately state is updated via context.read<CounterCubit>().increment(....) and a map with key named with the store name is created if its not created from before and add/update the product price/count there is two Maps one is for the price and the other for the counter

here is the state class

class CounterState extends Equatable {
  Map<int?, String?> storeNameperId;
  Map<String, Map<String, String>> storeNamePriceperProduct;
  Map<String, Map<String, int>> storeNameCounterperProduct;
  int? storeId;
  String? storeName;
  CounterState({
    this.storeId,
    this.storeName,
    required this.storeNameperId,
    required this.storeNamePriceperProduct,
    required this.storeNameCounterperProduct,
  });

  @override
  List<Object?> get props => [
    storeId,
    storeName,
    storeNameperId,
    storeNamePriceperProduct,
    storeNameCounterperProduct,
  ];
}

class CounterDecrementedState extends CounterState {
  CounterDecrementedState({
    super.storeId,
    super.storeName,
    required super.storeNameperId,
    required super.storeNamePriceperProduct,
    required super.storeNameCounterperProduct,
  });

  @override
  List<Object?> get props => [storeId, storeName];
}

class CounterInitialState extends CounterState {
  CounterInitialState({
    super.storeId,
    super.storeName,
    required super.storeNameperId,
    required super.storeNamePriceperProduct,
    required super.storeNameCounterperProduct,
  });

  @override
  List<Object?> get props => [storeId, storeName];
}

class CounterIncrementedState extends CounterState {
  CounterIncrementedState({
    super.storeId,
    super.storeName,
    required super.storeNameperId,
    required super.storeNamePriceperProduct,
    required super.storeNameCounterperProduct,
  });

  @override
  List<Object?> get props => [storeId, storeName];
}

here is the cubit class (all logic rests here except for decrement func btw)

class CounterCubit extends Cubit<CounterState> {
  CounterCubit()
    : super(
        CounterInitialState(
          storeId: 0,
          storeName: '',
          storeNameperId: {},
          storeNamePriceperProduct: {},
          storeNameCounterperProduct: {},
        ),
      );

  void increment(
    String productId,
    String price,
    int inputedId,
    String storeName,
  ) {
    final prevPriceMap = state.storeNamePriceperProduct[storeName];
    final prevCounterMap = state.storeNameCounterperProduct[storeName];

    final newPriceMap =
        prevPriceMap != null
            ? Map<String, String>.from(prevPriceMap)
            : <String, String>{};
    final newCounterMap =
        prevCounterMap != null
            ? Map<String, int>.from(prevCounterMap)
            : <String, int>{};

    newPriceMap[productId] = newPriceMap[productId] ?? price;
    newCounterMap[productId] = (newCounterMap[productId] ?? 0) + 1;

    final updatedStoreNameperPriceperProduct =
        Map<String, Map<String, String>>.from(state.storeNamePriceperProduct);
    final updatedStoreNamepercounterperProduct =
        Map<String, Map<String, int>>.from(state.storeNameCounterperProduct);

    updatedStoreNameperPriceperProduct[storeName] = newPriceMap;
    updatedStoreNamepercounterperProduct[storeName] = newCounterMap;

    emit(
      CounterIncrementedState(
        storeNameperId: {...state.storeNameperId, inputedId: storeName},
        storeNamePriceperProduct: updatedStoreNameperPriceperProduct,
        storeNameCounterperProduct: updatedStoreNamepercounterperProduct,
        storeId: state.storeId,
      ),
    );
  }
}

note : sorry if it seems kinda messy I still didn't organize it :)


Solution

  • A probable solution for this (based on a similar issue I faced earlier) could be the

    List<Object?> get props => [storeId, storeName];
    

    These props control whether a state is considered different from the previous one.

    So, even if your internal maps (storeNamePriceperProduct, etc.) change, the props list does not reflect those changes. As a result, emit() does not notify the listeners because it thinks the state hasn't changed.

    So u can try changing the props in

    CounterDecrementedState
    CounterInitialState
    CounterIncrementedState
    

    to

    List<Object?> get props => [
        storeId,
        storeName,
        storeNameperId,
        storeNamePriceperProduct,
        storeNameCounterperProduct,
      ];