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

React中如何获取Firebase集合每个文档的子集合数据

解决Firestore子集合数据获取问题

Firestore 查询主集合文档时,不会自动包含其下的子集合数据——子集合是独立的存储单元,必须单独发起查询才能获取。你之前尝试在转换器里映射invitedUsers,但它并不是主文档的字段,自然会返回undefined。

下面提供两种可行的实现方案:


方案1:逐行查询子集合(推荐,支持实时更新)

给表格每行单独创建子组件,在组件内部查询对应household的invitedUsers子集合,同时保留Firestore的实时更新特性。

步骤1:创建子组件 InvitedUsersList

import { collection } from "firebase/firestore";
import { useCollectionData } from "react-firebase-hooks/firestore";
import db from "../path-to-your-firebase-config";

// 定义InvitedUser类型
interface InvitedUser {
  id: string;
  name: string;
  // 按需添加其他字段
}

export default function InvitedUsersList({ householdId }: { householdId: string }) {
  const invitedUsersRef = collection(db, `households/${householdId}/invitedUsers`);
  const [invitedUsers, loading, error] = useCollectionData<InvitedUser>(invitedUsersRef);

  if (loading) return <span>加载中...</span>;
  if (error) return <span>加载失败:{error.message}</span>;
  if (!invitedUsers?.length) return <span>无邀请用户</span>;

  return (
    <ul>
      {invitedUsers.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

步骤2:在主组件中引入子组件

修改表格的邀请用户列代码:

<Td>
  <InvitedUsersList householdId={household.id} />
</Td>

方案2:批量预加载所有子集合数据(适合一次性加载场景)

如果不需要实时更新,或者希望一次性加载所有数据,可以在获取主集合后,批量查询所有子集合并合并到household数据中。

主组件修改代码:

import { useState, useEffect } from "react";
import { collection, getDocs } from "firebase/firestore";
import db from "../path-to-your-firebase-config";

// 复用InvitedUser类型定义
interface InvitedUser {
  id: string;
  name: string;
}

export default function MyComponent() {
  const householdsRef = collection(db, "households");
  const queryRef = query(
    householdsRef,
    where("participantsIds", "array-contains", user!.uid)
  );
  const collectionRef = queryRef.withConverter(householdConverter);
  const [households, householdLoading, householdError] = useCollectionData<Household>(collectionRef);
  
  // 存储合并了子集合数据的household列表
  const [householdsWithInvites, setHouseholdsWithInvites] = useState<(Household & { invitedUsers: InvitedUser[] })[] | null>(null);

  useEffect(() => {
    if (!households) return;

    const fetchAllInvitedUsers = async () => {
      // 批量查询每个household的子集合
      const promises = households.map(async (household) => {
        const invitedUsersSnap = await getDocs(collection(db, `households/${household.id}/invitedUsers`));
        const invitedUsers = invitedUsersSnap.docs.map(doc => ({
          id: doc.id,
          ...doc.data()
        })) as InvitedUser[];
        return { ...household, invitedUsers };
      });

      const result = await Promise.all(promises);
      setHouseholdsWithInvites(result);
    };

    fetchAllInvitedUsers();
  }, [households]);

  // 处理加载与错误状态
  if (householdLoading || !householdsWithInvites) return <div>加载中...</div>;
  if (householdError) return <div>加载失败:{householdError.message}</div>;

  return (
    <TableContainer>
      <Table>
        <Thead>
          <Tr>
            <Th>Household</Th>
            <Th>Owner</Th>
            <Th>Invited people</Th>
          </Tr>
        </Thead>
        <Tbody>
          {householdsWithInvites.map((household) => (
            <Tr key={household.id}>
              <Td>{household.name}</Td>
              <Td>{household.ownerName}</Td>
              <Td>
                <ul>
                  {household.invitedUsers.length === 0 ? (
                    <li>无邀请用户</li>
                  ) : (
                    household.invitedUsers.map((invitedUser) => (
                      <li key={invitedUser.id}>{invitedUser.name}</li>
                    ))
                  )}
                </ul>
              </Td>
            </Tr>
          ))}
        </Tbody>
      </Table>
    </TableContainer>
  );
}

额外注意事项

  • 确保Firebase安全规则允许读取households/{householdId}/invitedUsers子集合,否则会触发权限错误。
  • 方案1的实时更新依赖react-firebase-hooks的useCollectionData,若不需要实时同步,可替换为getDocs实现一次性查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:15:10