Home > Blockchain >  State not updating with Map using StateNotifier of Riverpod
State not updating with Map using StateNotifier of Riverpod

Time:10-14

I have an itemCount map with an ItemDescription keys and int values.

Map<ItemDescription, int> itemCount = {
  ItemDescription(
    name: 'Pepsi',
    price: 10,
  ): 1,
  ItemDescription(
    name: 'Coca-Cola',
    price: 12,
  ): 1,
};

I want to update the int value of the map in various places throughout my code, so I have defined the functions increment and decrement in a StateNotifier:

class ItemCountQuantity extends StateNotifier<Map<ItemDescription, int>> {
  ItemCountQuantity() : super(itemCount);

  void decrement(int index) {
    state.update(
      state.keys.elementAt(index),
      (value) {
        return --value;
      },
    );
  }

  void increment(int index) {
    state.update(
      state.keys.elementAt(index),
      (value) {
        return   value;
      },
    );
  }
}

The StateNotifierProvider for the above is defined as such:

final itemCountQuantity =
    StateNotifierProvider<ItemCountQuantity, Map<ItemDescription, int>>(
  (ref) => ItemCountQuantity(),
);

When I am calling ref.read(itemCountQuantity.notifier).decrement(index); or ref.read(itemCountQuantity.notifier).increment(index); in the onPressed parameter of a button, I can see that the value is updating but the state is not. Is there some error in my StateNotifier?

EDIT:

I tried setting the StateNotifier as such:

class ItemCountQuantity extends StateNotifier<Map<ItemDescription, int>> {
  ItemCountQuantity() : super(itemCount);

  void decrement(int index) {
    state = {
      ...state,
      state.keys.elementAt(index):
          state[state.keys.elementAt(index)]! - 1
    };
  }

  void increment(int index) {
    state = {
      ...state,
      state.keys.elementAt(index):
          state[state.keys.elementAt(index)]!   1
    };
  }
}

But neither did this work.

CodePudding user response:

Your issue is that you’re missing:

state = Map.of(state.update(…));
// instead of just
state.update(…);

This is because you need to assign the state to a new value so the StateNotifier knows something was updated. (state is implemented as a getter and setter under the hood.)

However, I’d like to note that doing state.keys.elementAt(index) feels very wrong when using a map, as it relies on the implementation of the map. If you must use the index to access an element, use a list of tuples. Or, just reference the map using its keys (and not an index).

CodePudding user response:

When you access your provider have you tried using the watch() method?

ref.read(itemCountQuantity.notifier).decrement(index)

to

ref.watch(itemCountQuantity.notifier).decrement(index)

read() will only get the value of/in provider just once (one-time read)

watch() get the value of/in provider the first time and every time the value changes

  • Related