I am using Riverpod 2.x for state management in Flutter shopping app. CartItem qty is not changing until after a screen switch or a manual action that causes a screen refresh. The same is true when adding a product to the cart screen, the visual checkmark showing that item is added is not shown. However, when I switch screen that rebuilds the widget, the correct and expected actions are displayed. I have set up providers with state notifiers to ensure instant change/rebuild but no luck. Here are the relevant code snippets:
updateItemQuantity() and addToCart():
void updateItemQuantity(String pId, int newQuantity, WidgetRef ref) {
if (cartItems.containsKey(pId)) {
final updatedQuantity = newQuantity;
// print('Updated Qty: $updatedQuantity');
if (updatedQuantity >= 1) {
state.update(
pId,
((value) => Cart(
cartId: value.cartId,
imageUrl: value.imageUrl,
title: value.title,
price: value.price,
quantity: updatedQuantity,
)),
);
} else {
state.remove(pId);
}
// state = {...state};
// ref.watch(cartProvider);
ref.read(cartProvider.notifier).state = {...state};
}
}
void addToCart(
String pId, String imageUrl, double price, String title, WidgetRef ref) {
if (cartItems.containsKey(pId)) {
state.update(
pId,
((value) => Cart(
cartId: value.cartId,
imageUrl: value.imageUrl,
title: value.title,
price: value.price,
quantity: value.quantity + 1,
)),
);
} else {
state.putIfAbsent(
pId,
() => Cart(
cartId: DateTime.now().toIso8601String(),
imageUrl: imageUrl,
title: title,
price: price,
quantity: 1,
),
);
}
// state = {...state};
// ref.watch(cartProvider);
ref.read(cartProvider.notifier).state = {...state};
}
cartController:
final cartProvider = StateNotifierProvider<CartListNotifier, Map<String, Cart>>(
(ref) => CartListNotifier(),
);
class CartListNotifier extends StateNotifier<Map<String, Cart>> {
CartListNotifier() : super(<String, Cart>{});
Map<String, Cart> get cartItems => {...state};
double get totalAmount {
double total = 0.0;
state.forEach((key, value) {
total += value.quantity * value.price;
});
return total;
}
TextButton(
// onPressed: productAttribute.quantity < 2
onPressed: cartItem?.quantity == null ||
cartItem?.quantity == 1
? () {}
: () {
ref
.read(cartProvider.notifier)
.updateItemQuantity(
productAttribute.id,
cartItem!.quantity - 1,
ref);
},
child: Text(
'-',
style: TextStyle(
fontSize:
Device.screenType == ScreenType.mobile
? 18.sp
: 20.sp,
),
),
),
Text(
cartItem?.quantity.toString() ?? '1',
style: TextStyle(
fontSize:
Device.screenType == ScreenType.mobile
? 18.sp
: 20.sp,
),
),
TextButton(
onPressed: () {
ref
.read(cartProvider.notifier)
.updateItemQuantity(productAttribute.id,
(cartItem?.quantity ?? 0) + 1, ref
// productAttribute.quantity + 1,
);
},
// },
child: Text(
'+',
style: TextStyle(
fontSize:
Device.screenType == ScreenType.mobile
? 18.sp
: 20.sp,
),
),
),
@override
Widget build(BuildContext context, WidgetRef ref) {
final productAttribute = ref.watch(productProvider.notifier).getById(pId);
final cartList = ref.watch(cartProvider.notifier);
final cartItem = cartList.cartItems[productAttribute.id];
double subTotal = cartItem!.quantity * productAttribute.price;