React/Firebase技术问题:无法从Firestore数据库中删除元素的排查求助
问题分析与解决方案
嘿,我一眼就揪出问题所在啦!你在添加商品到Firestore时踩了个常见小坑——你把自己生成的id作为文档的一个普通字段存储,但Firestore文档本身的ID是addDoc自动生成的,和你存在字段里的id完全不是一回事,这就导致删除时找不到对应的数据库文档。
具体问题拆解
看你的添加函数:
const handleClick = async(item) => { const newItem = { ...item, id: v4() } await addDoc(collection(db, 'cart_products'), { id: newItem.id, image: newItem.image, name: newItem.name, priceTotal: newItem.priceTotal, category: newItem.category }) setList([...list, newItem]) console.log(newItem) }
addDoc方法会自动为新文档生成一个随机ID,而你只是把自己用v4()生成的ID作为id字段写入了文档,但并没有把它设置为Firestore文档的ID。所以当你调用deleteDoc(doc(db, 'cart_products', id))时,传入的id是你自己生成的字段值,但Firestore根本找不到这个ID对应的文档(文档实际ID是addDoc返回的自动生成值),自然就删不掉数据库里的记录。
两种解决方案
方案一:用自定义ID作为Firestore文档ID(推荐)
让前端维护的id和Firestore文档ID保持一致,后续操作更省心。把addDoc换成setDoc,直接指定文档ID为你生成的newItem.id:
const handleClick = async(item) => { const newItem = { ...item, id: v4() } // 用setDoc指定文档ID为自定义的newItem.id await setDoc(doc(db, 'cart_products', newItem.id), { id: newItem.id, image: newItem.image, name: newItem.name, priceTotal: newItem.priceTotal, category: newItem.category }) setList([...list, newItem]) console.log(newItem) }
修改后你的删除函数完全不用动,因为现在deleteDoc传入的id就是Firestore文档的实际ID,能精准定位并删除目标文档。
方案二:删除时根据id字段查询文档再删除
如果不想改动添加逻辑,可以通过查询找到对应id字段的文档再删除:
const deleteProduct = async(id) => { // 查询所有id字段匹配的文档(理论上只有一条) const querySnapshot = await getDocs(query(collection(db, 'cart_products'), where('id', '==', id))) // 遍历结果删除对应文档 querySnapshot.forEach((doc) => { deleteDoc(doc.ref) }) setList((list) => list.filter((product) => id !== product.id)) }
不过这种方式需要额外查询,且如果出现重复id字段值可能误删其他文档,所以更推荐方案一。
内容的提问来源于stack exchange,提问作者Eugene Kliuchnikov
相关产品推荐
相关产品推荐

