Firestore文档更新老用户正常新用户报not-found错误求助
Firestore新用户更新文档失败问题排查与修复
问题根因
- 用户ID变量取值错误
你将当前用户ID变量ui定义在Edit(StatefulWidget类)中,而更新文档的代码处于State类_EditState内,如果你没有通过widget.ui的方式取值,而是直接调用ui,会出现变量取值错误的问题,导致构造的文档路径中的用户ID错误,找不到对应文档。另外直接在Widget类中初始化FirebaseAuth.instance.currentUser,如果页面是在登录流程完成前预构建的,新用户的currentUser可能返回空或者旧值,进一步加剧路径错误。 - 存储路径与业务逻辑不匹配
你当前的更新路径为/edit/{用户uid}/edit/{文档ID},属于用户私有子集合路径。而你的列表页是加载所有已添加的公开文档,老用户之前已经将公开文档同步到了自己的私有集合下,所以更新成功;新用户的私有集合下没有对应文档的副本,直接调用update()方法(该方法要求目标文档必须已存在)就会抛出not-found错误。 - 缺少校验与异常捕获
代码中没有对文档存在性做前置校验,也没有对update操作做异常捕获,无法兼容文档不存在的场景。
修复方案
第一步:修正用户ID的取值逻辑
将用户ID的取值移到State类的initState生命周期中,确保取值时用户已经完成登录,且State中可以正确访问到:
class Edit extends StatefulWidget { final DataModel data; const Edit({required this.data, super.key}); @override _EditState createState() => _EditState(); } class _EditState extends State<Edit> { // 移到State内部定义用户ID变量 late String uid; @override void initState() { super.initState(); // 先校验登录态,避免空指针 final user = FirebaseAuth.instance.currentUser; if (user == null) { // 未登录的跳转逻辑可自行补充 Navigator.pop(context); return; } uid = user.uid; } }
第二步:修正Firestore操作逻辑
根据你的业务场景二选一:
场景A:文档是公共文档,所有用户修改的是同一个公共文档
直接修改文档路径,不需要嵌套用户私有子集合:
onPressed: () async { // 公共文档路径,不需要带用户uid DocumentReference docRef = FirebaseFirestore .instance .collection('edit') .doc(widget.data.documentId); // 执行更新 await docRef.update({ // 补充你需要更新的字段 }); }
场景B:每个用户修改自己私有集合下的文档副本
新用户私有集合下没有对应文档时,用set()方法的合并模式替代update(),文档不存在时会自动创建,存在时会更新对应字段:
onPressed: () async { DocumentReference docRef = FirebaseFirestore .instance .collection('edit') .doc(uid) .collection('edit') .doc(widget.data.documentId); // 用SetOptions合并更新,兼容文档不存在的场景 await docRef.set({ // 补充你需要更新的字段 }, SetOptions(merge: true)); }
第三步:补充异常捕获
增加操作校验和异常提示,避免出现未捕获异常:
onPressed: () async { try { DocumentReference docRef = /* 替换为修正后的文档路径 */; // 先校验文档是否存在 final docSnapshot = await docRef.get(); if (!docSnapshot.exists) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("文档不存在"))); return; } await docRef.update({/* 补充更新字段 */}); ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("更新成功"))); } catch (e) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("更新失败:${e.toString()}"))); } }
内容的提问来源于stack exchange,提问作者akhicoda
相关产品推荐
相关产品推荐

