I'm trying to build remote shopping cart "I will add CRUD requests later" For now I'm just trying to build it using Riverpod NotifierProvider in the first stage.
I can fill my cart successfully However, I'm facing this error while displaying my items on the cart page.
════════ Exception caught by widgets library ═══════════════════════════════════ The following _CastError was thrown building: Null check operator used on a null value
here is my cart screen page:
class CartPage extends ConsumerWidget {
const CartPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(cartRepositoryProvider);
return Scaffold(
appBar: AppBar(
title: Text("Cart"),
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: state.length,
itemBuilder: (context, index) => ListTile(
title: Text(state.values.toList()[index].itemsName!),
// id: state.values.toList()[index].`!,
// itemsName: state.values.toList()[index].itemsName!,
// price: state.values.toList()[index].price!,
// qty: state.values.toList()[index].qty!,
// image: state.values.toList()[index].image!,
)),
)
],
),
));
}
}
also here is my cart_controller where I'm modifying the state based on my conditions.
class CartRepository extends Notifier<Map<String, CartItem>> {
@override
Map<String, CartItem> build() {
return {};
}
void addItem({required String productId, price, title, name, image}) {
if (state.containsKey(productId)) {
state.update(
productId,
(value) => CartItem(
productId: value.productId,
itemsName: value.itemsName,
price: value.price,
image: value.image,
qty: value.qty! + 1));
}
if (!state.containsKey(productId)) {
// cart.addAll({item.productId: item});
state.putIfAbsent(
productId,
() => CartItem(
productId: productId,
itemsName: title,
price: price,
image: image,
// productId: item.productId,
qty: 0),
);
}
}
void removeItem(String id) {
if (state.containsKey(id)) {
state.update(
id,
(value) => CartItem(
itemsName: value.itemsName,
price: value.price,
image: value.image,
productId: value.productId,
qty: value.qty! - 1));
}
}
void clearCart() {
state.clear();
}
getCartItem<String>(id) {
if (state.containsKey(id)) {
int quantity = state[id]!.qty ?? 0;
return quantity;
}
}
}
final cartRepositoryProvider =
NotifierProvider<CartRepository, Map<String, CartItem>>(CartRepository.new);
Furthermore, here is my cartItem Model:
import 'package:ecommerceriverpod/src/features/cart/domain/item.dart';
import 'package:ecommerceriverpod/src/features/products/domain/product.dart';
class CartItem {
String? productId;
String? itemsName;
String? price;
String? image;
int? qty;
CartItem({
required this.productId,
required this.itemsName,
required this.price,
required this.image,
required this.qty,
});
}
I'm sure it contains many mistakes but solving it will be highly appreciated. Also, I couldn't add the product_screen because of more code but I think this is enough.
Your problem is that you are accessing a CartItem
that does not exist
title: Text(state.values.toList()[index].itemsName!),
because the list will be empty at this point:
/// CartRepository
@override
Map<String, CartItem> build() {
return {};
}
Process the empty list in your widget:
if (state.isEmpty) return Text('Not found Cards');
Next, you must be very sure that your itemsName
field is not null. Either get rid of nullable fields in the CartItem
model, or handle each nullable field in your ui accordingly:
final item = state.values.toList()[index]!;
final itemName = item.itemsName ?? '';
title: Text(itemName),