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

如何按ID获取子集合中的单个文档?现有代码问题排查

问题分析与解决方案

现有代码存在的问题

  • 拼写错误:props.workotId 是笔误,正确应该是 props.workoutId,这个错误会导致永远匹配不到目标文档
  • 低效的数据获取逻辑:当前代码监听了整个workouts子集合,再遍历过滤目标ID的文档——完全没必要,Firebase支持直接通过文档ID定位单个文档,不需要拉取整个集合的数据
  • 缺失关键依赖项:useEffect的依赖数组为空,没有监听props.userId和props.workoutId的变化。当这两个属性更新时,组件不会重新发起数据请求,导致展示内容不同步
  • 冗余状态维护:workoutName状态完全多余,后续可以直接从workout对象中读取对应属性,不需要单独维护

修正后的代码实现

如果需要实时监听文档变化(文档更新时自动同步到组件),可以这样写:

import { doc, onSnapshot } from "firebase/firestore";
import { useState, useEffect } from "react";

export default function WorkoutInfo(props){
  const [workout, setWorkout] = useState(null);

  useEffect(() => {
    // 直接通过文档ID构建单个文档的引用
    const workoutDocRef = doc(db, "users", props.userId, "workouts", props.workoutId);
    
    // 监听单个文档的实时变化
    const unsubscribe = onSnapshot(workoutDocRef, (docSnapshot) => {
      if (docSnapshot.exists()) {
        setWorkout({ ...docSnapshot.data(), id: docSnapshot.id });
      } else {
        setWorkout(null); // 处理文档不存在的情况
        console.log("目标 workout 文档不存在");
      }
    }, (error) => {
      console.error("获取 workout 数据失败:", error);
    });

    // 组件卸载时取消监听
    return unsubscribe;
  }, [props.userId, props.workoutId]); // 添加依赖项,确保props变化时重新请求

  if (!workout) {
    return <div>加载中...</div>;
  }

  return (
    <div>
      <h2>{workout.name}</h2>
      {/* 按需展示其他workout信息 */}
    </div>
  );
}

如果不需要实时同步,只需要一次性获取数据,可以用getDoc替代onSnapshot:

import { doc, getDoc } from "firebase/firestore";
import { useState, useEffect } from "react";

export default function WorkoutInfo(props){
  const [workout, setWorkout] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const fetchWorkout = async () => {
      setIsLoading(true);
      try {
        const workoutDocRef = doc(db, "users", props.userId, "workouts", props.workoutId);
        const docSnapshot = await getDoc(workoutDocRef);
        
        if (docSnapshot.exists()) {
          setWorkout({ ...docSnapshot.data(), id: docSnapshot.id });
        } else {
          setWorkout(null);
          console.log("目标 workout 文档不存在");
        }
      } catch (error) {
        console.error("获取 workout 数据失败:", error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchWorkout();
  }, [props.userId, props.workoutId]);

  if (isLoading) {
    return <div>加载中...</div>;
  }

  if (!workout) {
    return <div>未找到该 workout</div>;
  }

  return (
    <div>
      <h2>{workout.name}</h2>
      {/* 按需展示其他workout信息 */}
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:02:47