Firebase更新用户文档报错:仅硬编码ID有效,如何获取正确文档ID?
问题场景
注册用户时通过createUserWithEmailAndPassword创建Auth用户,同时调用addDoc将用户信息存入Firestore的users集合。现在编写编辑组件时,用user.uid作为文档ID调用updateDoc,出现以下错误:
Uncaught (in promise) FirebaseError: No document to update: projects/teamh-test-tien/databases/(default)/documents/users/6BKmEeZeoXNYpgfM6ms6WbgH5as1.
只有硬编码Firestore自动生成的文档ID时,更新才能正常执行;用setDoc+merge:true的方式会创建一个以user.uid为ID的新文档,和原注册生成的文档并存。
核心原因
你的注册代码中使用addDoc(collection(db, "users"), {...}),这个方法会让Firestore自动生成随机的文档ID,而你只是把user.uid作为文档的一个字段(uid: user.uid)存入,并没有将文档ID设置为user.uid。这就导致:
- Firestore中用户文档的ID是随机字符串
- 你更新时用的
user.uid是Auth用户的ID,和文档ID不匹配,自然找不到对应文档
解决方案
方案1:修改注册逻辑,将文档ID设置为user.uid(推荐)
这是最直接的方式,后续更新、查询都可以直接用user.uid定位文档:
const registerWithEmailAndPassword = async (name, email, password) => { try { const auth = getAuth(); const res = await createUserWithEmailAndPassword(auth, email, password); const user = res.user; // 用setDoc指定文档ID为user.uid,替代addDoc await setDoc(doc(db, "users", user.uid), { uid: user.uid, name, authProvider: "local", email, }); await updateProfile(user,{ displayName: name, }) await user.reload() } catch (err) { console.error(err); alert(err.message); } };
修改后,你的原有更新代码handleUpdate就能正常工作,无需改动。
方案2:保留现有注册逻辑,通过uid字段查询文档ID后更新
如果不想修改已有的注册数据,可以在更新时先通过user.uid查询对应的文档,再获取文档ID进行更新:
const handleUpdate = async (e) => { e.preventDefault(); // 查询users集合中uid等于当前用户uid的文档 const querySnapshot = await getDocs(collection(db, "users")); let targetDocRef = null; querySnapshot.forEach((doc) => { if (doc.data().uid === user.uid) { targetDocRef = doc.ref; } }); if (!targetDocRef) { console.error('未找到对应用户的文档'); return; } await updateDoc(targetDocRef, { name, }).then(() => console.log('更新成功!', auth.currentUser.displayName)); };
优化建议:为users集合的uid字段创建索引,避免大量数据时查询性能问题。
内容的提问来源于stack exchange,提问作者Tien

