Firestore查询报错:collection()参数不符合预期问题求助
执行Firestore查询时遇到以下错误:
FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore
怀疑是getFirestore()传参问题,以下是相关代码:
数据库初始化代码
import { initializeApp } from "firebase/app"; import { getFirestore, connectFirestoreEmulator } from "@firebase/firestore/lite"; class Db { static firebaseApp = null; constructor() { if (!Db.firebaseApp) { Db.firebaseApp = initializeApp({ apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", }); const useEmulator = process.env.NODE_ENV === "development"; this.db = getFirestore(); if (useEmulator) { const emulatorHost = "192.168.1.51"; const emulatorPort = 8080; connectFirestoreEmulator(this.db, emulatorHost, emulatorPort); } } } } export default Db;
使用static属性是为了避免重复初始化App,防止触发:
FirebaseError: Firestore has already been started and its settings can no longer be changed. You can only modify settings before calling any other methods on a Firestore object.
查询代码
import { collection, getDocs, query, where } from "@firebase/firestore/lite"; import Db from "./DataBase.js"; class SignUpClientSide extends Db { async checkUsernameUniqueness(username) { const usersRef = collection(this.db, "users"); console.log(usersRef); const lowercaseQuerySnapshot = await getDocs(query(usersRef, where("username", "==", username.toLowerCase()))); console.log(lowercaseQuerySnapshot); const uppercaseQuerySnapshot = await getDocs(query(usersRef, where("username", "==", username.toUpperCase()))); if (!lowercaseQuerySnapshot.empty || !uppercaseQuerySnapshot.empty) { return false; } return true; } }
错误原因
Db类中仅第一次实例化时,会进入if (!Db.firebaseApp)代码块并给this.db赋值。后续实例化时,因Db.firebaseApp已存在,不会执行该代码块,导致this.db为undefined。调用collection(this.db, "users")时,第一个参数不符合要求,触发报错。
修复方案
将db也设为static属性,确保所有实例共享同一个Firestore实例,同时在构造函数中同步给当前实例赋值:
import { initializeApp } from "firebase/app"; import { getFirestore, connectFirestoreEmulator } from "@firebase/firestore/lite"; class Db { static firebaseApp = null; static db = null; constructor() { if (!Db.firebaseApp) { Db.firebaseApp = initializeApp({ apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", }); const useEmulator = process.env.NODE_ENV === "development"; Db.db = getFirestore(Db.firebaseApp); if (useEmulator) { const emulatorHost = "192.168.1.51"; const emulatorPort = 8080; connectFirestoreEmulator(Db.db, emulatorHost, emulatorPort); } } this.db = Db.db; } } export default Db;
也可以选择不使用static db,在构造函数中直接获取实例:
constructor() { if (!Db.firebaseApp) { // 原有初始化app和db的代码 } else { this.db = getFirestore(Db.firebaseApp); } }
注意:调用getFirestore()时,建议显式传入Firebase App实例,避免隐式依赖默认App可能引发的问题。
内容的提问来源于stack exchange,提问作者Artis84

