Firebase报错db.collection is not a function 如何按文档ID获取用户数据
报错原因
你遇到的TypeError: _firebase__WEBPACK_IMPORTED_MODULE_5__.db.collection is not a function本质是Firebase SDK版本和写法不匹配:你项目里用的是v9+的模块化SDK,而db.collection("users").doc()是v8及更早版本的命名空间链式调用语法,v9版本的db实例上根本没有挂载collection方法,自然会抛错。
除了API写法错误,你现有代码还有几个逻辑问题,就算改对API也拿不到数据:
- 漏了Firestore查询所需的方法导入,也没定义
userData对应的state就直接调用setUserData - Firestore的
get()是异步操作,直接同步赋值拿到的只是Promise对象,不是实际文档数据 onAuthStateChanged没有放在副作用里执行,组件每次重渲染都会重复注册监听器,而且初始userId是空字符串,会拿着空值去查文档- 没有判断查询到的文档是否存在,遇到空文档直接读数据会报错
修复方案
- 先把Firestore需要用到的方法补全导入,替换你原来的firestore导入行:
import { doc, getDoc } from "firebase/firestore";
- 把旧版的链式查询替换成v9模块化写法,同时修复异步、监听器的逻辑问题,完整可用代码如下:
import { useState, useEffect } from 'react'; import { getAuth, onAuthStateChanged } from "firebase/auth"; import { doc, getDoc } from "firebase/firestore"; import { db } from '../../firebase'; const Single = () => { const [userId, setUserId] = useState(""); // 补全userData的state定义 const [userData, setUserData] = useState(null); const auth = getAuth(); useEffect(() => { // 注册auth状态监听,组件卸载时注销监听避免内存泄漏 const unsubscribe = onAuthStateChanged(auth, async (user) => { if (user) { const uid = user.uid; setUserId(uid); // v9语法构建文档引用:doc(db实例, 集合名, 文档ID) const userDocRef = doc(db, "users", uid); // 异步等待查询结果 const docSnapshot = await getDoc(userDocRef); if (docSnapshot.exists()) { // 调用.data()拿到文档里存储的实际字段数据 const data = docSnapshot.data(); setUserData(data); console.log("查询到的用户数据:", data); } else { console.log("users集合下未找到ID对应当前用户的文档,请确认你写入用户数据时用的文档ID就是用户uid"); } } else { // 未登录场景清空状态 setUserId(""); setUserData(null); } }); // 组件卸载时执行注销逻辑 return () => unsubscribe(); }, [auth]) // 后续直接用userData渲染页面即可 return ( <div className="user-profile"> {userData ? ( <div> <p>用户ID:{userId}</p> <p>用户名:{userData.username}</p> {/* 其他用户字段按需渲染 */} </div> ) : ( <p>用户信息加载中...</p> )} </div> ) } export default Single;
注意事项
- 别混用v8和v9的Firebase写法,v9模块化的单文档查询固定用
getDoc,集合查询用getDocs,构建引用不要走db实例的链式调用 - 所有Firestore读写操作都是异步的,必须加
await或者.then()拿结果,不要同步读取返回值 - 查单文档拿到快照后一定要先调
exists()判断文档是否存在,不然如果对应ID的文档没创建,直接调.data()会抛错 onAuthStateChanged会持续监听用户登录状态变化,一定要在组件卸载时注销,不然会造成内存泄漏和重复触发查询
内容的提问来源于stack exchange,提问作者Prakash Subba
相关产品推荐
相关产品推荐

