Home > OS >  Flutter riverpod incrementing state with notifier
Flutter riverpod incrementing state with notifier

Time:09-13

In previous versions of Riverpod i can easily increment some data in state by copyWith but in riverpod: ^1.0.3 version of this library i can't do that. for example:

/* click event to increment */
ref.read(orderStructureProvider.notifier).increment(breadId: id);

order notifier:

final orderStructureProvider = StateNotifierProvider<OrderNotifier, OrderStructure>((ref) => OrderNotifier());

class OrderNotifier extends StateNotifier<OrderStructure> {
  OrderNotifier() : super(_initial);

  static const OrderStructure _initial = OrderStructure(
    address: Address(
      address: 'address',
      province: {},
      city: {},
      neighbourhood: {},
    ),
    breads: [],
    baker: [],
    paymentType: 1,
  );

  void resetOrder() => state = _initial;

  int breadsCount() => state.breads.length;

  void updateAddress(
    String _address,
    Map<String, dynamic> _province,
    Map<String, dynamic> _city,
    Map<String, dynamic> _neighbourhood,
  ) {
    state = OrderStructure(
      address: Address(
        address: _address,
        province: _province,
        city: _city,
        neighbourhood: _neighbourhood,
      ),
      breads: [...state.breads],
      baker: [],
      paymentType: state.paymentType,
    );
  }

  BreadStructure? getService(int breadId) {
    final index = state.breads.indexWhere((bread) => bread.id == breadId);
    return index >= 0 ? state.breads[index] : null;
  }

  void create(BreadStructure _bread) {
    final newState = OrderStructure(
      address: state.address,
      breads: [...state.breads, _bread],
      baker: [...state.baker],
      paymentType: state.paymentType,
    );
    //newState.breads=[...state.breads,_bread];
    state = newState;
  }

  bool breadExists(int breadId) => state.breads.indexWhere((bread) => bread.id == breadId) == -1;

  void increment({required int breadId}) {
    final newState = OrderStructure(
      address: state.address,
      breads: [...state.breads],
      baker: [...state.baker],
      paymentType: state.paymentType,
    );

    debugPrint(state.breads.toString());
    final int index = newState.breads.indexWhere((element) => element.id == breadId);
    newState.breads[index].copyWith(count: 44);
    //debugPrint(newState.breads.toString());
    state = newState;
  }

  void decrement(int breadId) {
    final newState = OrderStructure(
      address: state.address,
      breads: [...state.breads],
      baker: [...state.baker],
      paymentType: state.paymentType,
    );

    final index = state.breads.indexWhere((element) => element.id == breadId);
    BreadStructure bread = newState.breads[index];
    if (index >= 0) {
      if (bread.count <= 1) {
        newState.breads.removeAt(index);
      } else {
        bread = bread.copyWith(count: bread.count - 1);
      }
    }

    state = newState;
  }
}

@freezed
abstract class OrderStructure with _$OrderStructure {
  const factory OrderStructure({
    required Address address,
    required List<BreadStructure> breads,
    required List<Map<String, dynamic>> baker,
    required int paymentType,
  }) = _OrderStructure;

  factory OrderStructure.fromJson(Map<String, dynamic> json) => _$OrderStructureFromJson(json);
}

@freezed
abstract class Address with _$Address {
  const factory Address({
    required String address,
    required Map<String, dynamic> province,
    required Map<String, dynamic> city,
    required Map<String, dynamic> neighbourhood,
  }) = _Address;

  factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
}

@freezed
abstract class BreadStructure with _$BreadStructure {
  const factory BreadStructure({
    required int id,
    required String name,
    required int count,
  }) = _BreadStructure;

  factory BreadStructure.fromJson(Map<String, dynamic> json) => _$BreadStructureFromJson(json);
}

output:

0
1
1
1
1
1
...

CodePudding user response:

The problem is

newState.breads[index].copyWith(count: 44);

copyWith() is returning new instance with modified parameters not editing current one.

solution

void increment({required int breadId}) {
    final int index = state.breads.indexWhere((bread) => bread.id == breadId);
    final bread = state.breads[index];

    final updatedBread = bread.copyWith(count: bread.count   1);
    
    /* save to state */
    state = state.copyWith(
      breads: List.from(state.breads)..[index] = updatedBread,
    );
  }
  • Related