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

React中从Firestore获取含嵌套集合的对象格式数据问题求助

How to Fetch Nested Firestore Collections as a Nested Object in React

Let's break down how to solve this problem step by step, since your current attempts are hitting common Firestore structure and async pitfalls.

First, let's clarify your Firestore structure to make sure we're on the same page:

members (collection)
└── JhonDoe (document, may have no stored data)
    └── May (subcollection)
        └── 28 (document)
            ├── expense: "1"
            ├── gain: "2"
            └── name: "Jhon Doe"

The Correct Approach

To get nested subcollections under a document and format them into your desired object structure, you need to:

  1. Reference the parent member document
  2. List all subcollections under that document (like May)
  3. Fetch all documents in each subcollection
  4. Assemble the data into the nested object format you want

Here's a working implementation using Firebase v9 (modular SDK, the current standard):

import { doc, getFirestore, listCollections, getDocs } from "firebase/firestore";

export const getMembersDailyGains = async (name) => {
  const db = getFirestore();
  const dbName = name.replace(/\s/g, "");
  
  // Get reference to the member's document (even if it has no data)
  const memberDocRef = doc(db, "members", dbName);
  
  try {
    const nestedData = {};
    
    // Fetch all subcollections under the member document
    const subcollections = await listCollections(memberDocRef);
    
    for (const monthCollection of subcollections) {
      const monthName = monthCollection.id; // e.g., "May"
      nestedData[monthName] = {};
      
      // Fetch all documents in this month's subcollection
      const dateDocs = await getDocs(monthCollection);
      dateDocs.forEach(dateDoc => {
        const dateId = dateDoc.id; // e.g., "28"
        nestedData[monthName][dateId] = dateDoc.data();
      });
    }
    
    console.log("Fetched nested data:", nestedData);
    return nestedData;
  } catch (error) {
    console.error("Error fetching data:", error);
    return {};
  }
};

Using This in Your React Component

Since this is an async function, you'll need to handle it properly in your component to avoid pending promises:

import { useEffect, useState } from "react";
import { getMembersDailyGains } from "./path-to-your-function";

function MemberGains() {
  const [gainsData, setGainsData] = useState({});
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const fetchGains = async () => {
      const data = await getMembersDailyGains("Jhon Doe");
      setGainsData(data);
      setIsLoading(false);
    };
    
    fetchGains();
  }, []);

  if (isLoading) return <div>Loading daily gains...</div>;

  return (
    <div>
      <h3>Jhon Doe's Daily Gains</h3>
      <pre>{JSON.stringify(gainsData, null, 2)}</pre>
    </div>
  );
}

export default MemberGains;

Why Your Previous Attempts Failed

Let's diagnose the issues in your code:

  1. First Attempt Error: Invalid collection reference

    • members/${dbName} is a document path (2 segments: members → JhonDoe), but Firestore collection references require an odd number of segments. You were trying to treat a document as a collection, which doesn't work. You need to target the document first, then access its subcollections.
  2. Second Attempt Error: No such document!

    • Firestore allows documents to have subcollections even if the parent document itself doesn't exist (or has no stored data). Your JhonDoe document likely has no fields, so doc.exists returned false, but that doesn't mean its subcollections aren't there. You were fetching the document's data instead of its subcollections.
  3. Pending Promise Issue:

    • You mixed await and .then() incorrectly, and returned gainsList before the async operations finished. Using consistent await syntax ensures you wait for all data to be fetched before returning the result.

Note on Firestore vs. Realtime Database

Firestore uses a document-collection hierarchy, unlike Realtime Database's single tree structure. This means subcollections are tied to documents, but you can't access them via a single path like you do in Realtime Database. The approach above mirrors the structure you used in Realtime Database but adapts it to Firestore's model.

内容的提问来源于stack exchange,提问作者Biki Thakur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:12:47