You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中setState引发商品购物车按钮状态混乱问题求助

解决Flutter商品购物车状态混淆问题

问题根源

  1. 购物车状态查询逻辑错误:遍历用户购物车文档时,每遇到一个不匹配的商品就会将isCarted设为false,导致最后一个不匹配的文档会覆盖之前找到的匹配结果。
  2. 频繁重复请求Firestore:在build方法中调用getdata(),每次组件重建都会触发数据查询,引发不必要的状态更新。
  3. 移除购物车操作逻辑错误:点击移除按钮时删除了用户购物车下的所有文档,而非仅当前商品对应的文档。
  4. 状态初始化时机错误:未在组件初始化阶段加载购物车状态,导致初始状态可能与实际数据不符。

修复步骤

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 01:22:05