Firestore跨集合查询报错:Uncaught (in promise) TypeError: doc2 is not a function
问题:Firestore关联查询报错TypeError: doc is not a function
需要从orders集合的每条订单中,通过UID关联users集合获取display_name,通过AID关联artworks集合获取图片名称,在订单列表页展示时触发以下错误:
Uncaught (in promise) TypeError: doc is not a function at getOrders (ordersList.jsx:27:23)
orders集合包含UID、AID等关联字段,当前实现代码:
import React, { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import {collection, doc, getDocs, getDoc, orderBy, query, } from "firebase/firestore"; import { db } from "../../firebase"; import { format } from "date-fns"; export default function UsersList() { const [ordersList, setOrdersList] = useState([]); const timestampToDate = (timestamp) => new Date(timestamp.seconds * 1000); const getOrders = async () => { const ordersRef = collection(db, "orders"); const q = query(ordersRef, orderBy("timestamp", "desc")); const querySnapshot = await getDocs(q); const newData = []; for (const doc of querySnapshot.docs) { const orderData = doc.data(); const userRef = doc(db, "users", orderData.UID.toString().toUpperCase()); const userDoc = await getDoc(userRef); const userData = userDoc.data(); const artworkRef = doc(db, "artworks", orderData.AID.toString().toUpperCase()); const artworkDoc = await getDoc(artworkRef); const artworkData = artworkDoc.data(); newData.push({ id: doc.id, userDisplayName: userData?.display_name || "", artworkName: artworkData?.name || "", artworkImage: artworkData?.image || "", ...orderData, }); } setOrdersList(newData); console.log(ordersList, newData); }; useEffect(() => { getOrders(); }, []); return ( // data table ); }
错误原因
循环中使用for (const doc of querySnapshot.docs),这里的doc变量覆盖了从Firebase Firestore导入的同名doc方法。后续调用doc(db, "users", ...)时,doc已经是循环中的订单文档对象,不再是创建文档引用的函数,因此触发类型错误。
修复方案
将循环内的变量名改为与导入的doc方法不冲突的名称(比如orderDoc),修改后的核心代码如下:
const getOrders = async () => { const ordersRef = collection(db, "orders"); const q = query(ordersRef, orderBy("timestamp", "desc")); const querySnapshot = await getDocs(q); const newData = []; // 把循环变量名改为orderDoc,避免覆盖导入的doc方法 for (const orderDoc of querySnapshot.docs) { const orderData = orderDoc.data(); const userRef = doc(db, "users", orderData.UID.toString().toUpperCase()); const userDoc = await getDoc(userRef); const userData = userDoc.data(); const artworkRef = doc(db, "artworks", orderData.AID.toString().toUpperCase()); const artworkDoc = await getDoc(artworkRef); const artworkData = artworkDoc.data(); newData.push({ id: orderDoc.id, userDisplayName: userData?.display_name || "", artworkName: artworkData?.name || "", artworkImage: artworkData?.image || "", ...orderData, }); } setOrdersList(newData); };
额外优化建议
- 批量获取关联文档:当前循环中每次迭代都发起两次异步请求,大量订单时性能较差。可以用
Promise.all批量处理所有用户和作品的查询请求,减少网络请求次数。 - 添加错误捕获:在
getOrders函数中加入try/catch块,处理Firestore查询可能出现的异常,避免页面崩溃。
内容的提问来源于stack exchange,提问作者DaggerK
相关产品推荐
相关产品推荐

