I'm following a tutorial for a shopping cart using getx and I've encountered a problem where when the cart is empty I receive "bad state no element" error. I know it is because .reduce method when the list is empty it produces such an error but when I try to use .fold I get an error like this: "The return type 'num' isn't a 'int', as required by the closure's context".
there is only one question I found and the problem is identical to mine but the I did not understand the chosen answer. I've been trying to search for answers on how to solve it but so far none of the answers worked for me.
here is the link for the question : How to identify the List is empty, to avoid the Bad state: No element for ListMixin.reduce
Here is my cart controller:
import 'package:get/get.dart';
import 'package:plantel/screens/widgets/product_model.dart';
class CartController extends GetxController {
final _products = {}.obs;
void addProduct(Product product) {
if (_products.containsKey(product)) {
_products[product] += 1;
} else {
_products[product] = 1;
}
}
void removeProduct(Product product) {
if (_products.containsKey(product) && _products[product] == 1) {
_products.removeWhere((key, value) => key == product);
} else {
_products[product] -= 1;
}
}
get productSubtotal => _products.entries
.map((product) => product.key.price * product.value)
.toList();
get total => _products.entries
.map((product) => product.key.price * product.value)
.toList()
.reduce((value, element) => value + element)
.toStringAsFixed(2);
get products => _products;
}
here is the product controller, I'm using Cloud Firestore database to fetch the lists.
import 'package:get/get.dart';
import 'package:plantel/screens/widgets/firestore_db.dart';
import 'package:plantel/screens/widgets/product_model.dart';
class InDoorProductController extends GetxController {
final products = <Product>[].obs;
@override
void onInit() {
products.bindStream(FirestoreDB().getInDoorProducts());
super.onInit();
}
}
class OutDoorProductController extends GetxController {
final products = <Product>[].obs;
@override
void onInit() {
products.bindStream(FirestoreDB().getOutdoorProducts());
super.onInit();
}
}
class PotsAndVasesProductController extends GetxController {
final products = <Product>[].obs;
@override
void onInit() {
products.bindStream(FirestoreDB().getpotsandvasesProducts());
super.onInit();
}
}
class SoilsProductController extends GetxController {
final products = <Product>[].obs;
@override
void onInit() {
products.bindStream(FirestoreDB().getsoilsProducts());
super.onInit();
}
}
class PesticidesProductController extends GetxController {
final products = <Product>[].obs;
@override
void onInit() {
products.bindStream(FirestoreDB().getpesticidesProducts());
super.onInit();
}
}
Here is the FirestoreDB class to fetch the collections.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:plantel/screens/widgets/product_model.dart';
class FirestoreDB {
final FirebaseFirestore _firebaseFirestoreindoor = FirebaseFirestore.instance;
Stream<List<Product>> getInDoorProducts() {
return _firebaseFirestoreindoor
.collection('indoorplants')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
});
}
final FirebaseFirestore _firebaseFirestoreoutdoor =
FirebaseFirestore.instance;
Stream<List<Product>> getOutdoorProducts() {
return _firebaseFirestoreoutdoor
.collection('outdoorplants')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
});
}
final FirebaseFirestore _firebaseFirestorepotsandvases =
FirebaseFirestore.instance;
Stream<List<Product>> getpotsandvasesProducts() {
return _firebaseFirestorepotsandvases
.collection('potsandvases')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
});
}
final FirebaseFirestore _firebaseFirestoresoils = FirebaseFirestore.instance;
Stream<List<Product>> getsoilsProducts() {
return _firebaseFirestorepotsandvases
.collection('soils')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
});
}
final FirebaseFirestore _firebaseFirestorepesticides =
FirebaseFirestore.instance;
Stream<List<Product>> getpesticidesProducts() {
return _firebaseFirestorepotsandvases
.collection('pesticides')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
});
}
}
here is the product model
import 'package:cloud_firestore/cloud_firestore.dart';
class Product {
final String title;
final int price;
final String subtitle;
final String image;
const Product(
{required this.title,
required this.price,
required this.subtitle,
required this.image});
static Product fromSnapshot(DocumentSnapshot snap) {
Product product = Product(
title: snap['title'],
price: snap['price'],
subtitle: snap['subtitle'],
image: snap['image']);
return product;
}
}
My apologies if I've added unnecessary code blocks but I've added them in case someone wanted to get the full picture on how I got the lists.
EDIT 1: I just solved it thanks to @pskink for his suggestion. I got it working like this.
.fold(0, (value, element) => (value + element).toInt());