You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:05:42