Flutter中setState引发商品购物车按钮状态混乱问题求助
解决Flutter商品购物车状态混淆问题
问题根源
- 购物车状态查询逻辑错误:遍历用户购物车文档时,每遇到一个不匹配的商品就会将
isCarted设为false,导致最后一个不匹配的文档会覆盖之前找到的匹配结果。 - 频繁重复请求Firestore:在
build方法中调用getdata(),每次组件重建都会触发数据查询,引发不必要的状态更新。 - 移除购物车操作逻辑错误:点击移除按钮时删除了用户购物车下的所有文档,而非仅当前商品对应的文档。
- 状态初始化时机错误:未在组件初始化阶段加载购物车状态,导致初始状态可能与实际数据不符。
修复步骤
1. 修正购物车状态查询逻辑
遍历购物车文档时,找到匹配商品后立即停止遍历,避免后续不匹配文档覆盖正确状态:
getdata() async { if (FirebaseAuth.instance.currentUser != null) { bool found = false; final querySnapshot = await FirebaseFirestore.instance .collection('Admin') .doc('products') .collection('IsCarted') .doc(FirebaseAuth.instance.currentUser!.uid) .collection("UserData") .get(); for (var doc in querySnapshot.docs) { if (doc["CartedDoc"] == widget.docId) { found = true; break; // 找到匹配项就停止遍历 } } setState(() { isCarted = found; }); } }
2. 调整数据查询时机
将getdata()移到initState中,仅在组件初始化时获取一次购物车状态,避免build阶段重复请求:
@override void initState() { super.initState(); getdata(); } @override Widget build(BuildContext context) { // 移除build方法内的getdata()调用 return Container( // 原有布局代码... ); }
3. 修复移除购物车操作逻辑
仅删除当前商品对应的购物车文档,而非全部清空:
onPressed: () async { if (FirebaseAuth.instance.currentUser != null) { final collref = FirebaseFirestore.instance .collection('Admin') .doc('products') .collection('IsCarted') .doc(FirebaseAuth.instance.currentUser!.uid) .collection("UserData"); // 查询当前商品对应的购物车文档并删除 final snapshot = await collref.where("CartedDoc", isEqualTo: widget.docId).get(); for (var doc in snapshot.docs) { await doc.reference.delete(); } setState(() { isCarted = false; }); } },
修改后的完整代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:groccer_app/Drawer/categories/prodetails.dart'; import 'package:add_to_cart_animation/add_to_cart_animation.dart'; class Products extends StatefulWidget { final String imgUrl; final String title; final String quantity; final String prodetail; final String price; final Function ontap; final String docId; const Products({ super.key, required this.imgUrl, required this.title, required this.quantity, required this.price, required this.prodetail, required this.ontap, required this.docId, }); @override State<Products> createState() => _ProductsState(); } class _ProductsState extends State<Products> { bool isCarted = false; getdata() async { if (FirebaseAuth.instance.currentUser != null) { bool found = false; final querySnapshot = await FirebaseFirestore.instance .collection('Admin') .doc('products') .collection('IsCarted') .doc(FirebaseAuth.instance.currentUser!.uid) .collection("UserData") .get(); for (var doc in querySnapshot.docs) { if (doc["CartedDoc"] == widget.docId) { found = true; break; } } setState(() { isCarted = found; }); } } @override void initState() { super.initState(); getdata(); } @override Widget build(BuildContext context) { return Container( child: widget.imgUrl != "" && widget.price != "" && widget.title != "" && widget.prodetail != "" && widget.quantity != "" ? Column(children: [ GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => productDetails( detail: widget.prodetail, imageUrl: widget.imgUrl, price: widget.price, title: widget.title, quantity: widget.quantity, ), ), ); }, child: Card( child: Padding( padding: const EdgeInsets.all(20.0), child: Row( children: [ Container( width: 60, height: 60, color: Colors.transparent, child: Image.network(widget.imgUrl), ), const SizedBox(width: 16.0), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: MediaQuery.of(context).size.width, child: Text( widget.title, style: const TextStyle( fontWeight: FontWeight.w500, fontSize: 15), ), ), const SizedBox(height: 7.0), Text( widget.quantity, style: const TextStyle( overflow: TextOverflow.ellipsis, fontSize: 16, fontWeight: FontWeight.w400, color: Color.fromRGBO(146, 146, 146, 1.0)), ), const SizedBox(height: 50.0), Text( "Rs: " + widget.price, style: const TextStyle( fontWeight: FontWeight.w800, fontSize: 17, color: Color.fromRGBO(230, 0, 57, 1.0)), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ const SizedBox(height: 40), const Icon( Icons.arrow_forward_ios_rounded, color: Color.fromRGBO(193, 193, 193, 1.0), ), const SizedBox(height: 30), isCarted == false ? ElevatedButton( onPressed: () async { final collref = FirebaseFirestore.instance .collection('Admin') .doc('products') .collection('IsCarted') .doc(FirebaseAuth .instance.currentUser!.uid) .collection("UserData"); await collref .add({"CartedDoc": widget.docId}); setState(() { isCarted = true; }); }, child: const Text( "Add to Cart", style: TextStyle( color: Color.fromRGBO( 191, 232, 203, 1.0)), ), style: ElevatedButton.styleFrom( backgroundColor: const Color.fromRGBO( 25, 174, 68, 1.0), elevation: 0), ) : ElevatedButton( onPressed: () async { if (FirebaseAuth.instance.currentUser != null) { final collref = FirebaseFirestore.instance .collection('Admin') .doc('products') .collection('IsCarted') .doc(FirebaseAuth .instance.currentUser!.uid) .collection("UserData"); final snapshot = await collref .where("CartedDoc", isEqualTo: widget.docId) .get(); for (var doc in snapshot.docs) { await doc.reference.delete(); } } setState(() { isCarted = false; }); }, style: ButtonStyle( backgroundColor: MaterialStateColor.resolveWith( (states) => Colors.white), elevation: MaterialStateProperty.resolveWith( (states) => 0), side: MaterialStateProperty.resolveWith< BorderSide>( (Set<MaterialState> states) { return BorderSide( color: const Color.fromRGBO( 25, 174, 68, 1.0), width: 3); }, )), child: const Row( children: [ Icon( Icons.delete, color: Colors.black, ), ], ), ) ], ), ], ), ), ), ) ]) : Container(), ); } }
内容的提问来源于stack exchange,提问作者Ammar Mohib
相关产品推荐
相关产品推荐

