如何在ReactJS中通过用户UID从Firestore的data集合获取单个文档
解决Firestore获取单个用户文档而非全部集合的问题
你的问题核心在于错误地用onSnapshot监听了整个data集合,而不是用户UID对应的单个文档。代码里dbRef指向的是整个data集合,所以onSnapshot会返回集合内所有文档的数据,这就是你拿到全部内容的原因。
修复方案
以下是调整后的代码,重点修改了监听目标、逻辑简化和内存泄漏处理:
export default function Nutrition() { const [data, setData] = useState([]); useEffect(() => { let unsubscribe; onAuthStateChanged(auth, (user) => { if (user) { const uid = user.uid; // 创建当前用户对应文档的引用,而非整个集合 const userDocRef = doc(db, "data", uid); // 监听单个文档的实时变化 unsubscribe = onSnapshot(userDocRef, (docSnapshot) => { if (docSnapshot.exists()) { const { value, quantity } = docSnapshot.data(); let foods = []; // 仅处理当前用户文档内的数据 for (let i = 0; i < value.length; i++) { foods.push({ value: value[i], quantity: quantity[i] }); } setData(foods); } else { console.log("User doc missing"); setData([]); } }); } else { console.log("User not logged in"); setData([]); } }); // 组件卸载时取消监听,避免内存泄漏 return () => { if (unsubscribe) unsubscribe(); }; }, []); return ( <React.Fragment> <div className='container mt-3'> <table className='table table-hover'> <thead> <tr> <th>#</th> <th>Food</th> <th>Quantity</th> </tr> </thead> <tbody> {data.map((row, index) => ( <tr key={index}> <td>{index + 1}</td> <td>{row.value}</td> <td>{row.quantity}</td> </tr> ))} </tbody> </table> </div> </React.Fragment> ); }
关键修改说明
- 替换监听目标:将集合引用改为单个文档引用
doc(db, "data", uid),确保只监听当前用户的文档 - 简化逻辑:移除多余的
getDoc调用,onSnapshot会自动触发初始数据获取和后续变化监听 - 内存泄漏处理:在
useEffect返回函数中取消onSnapshot订阅,避免组件卸载后残留监听 - 修正key值:将
map中的错误key={data.id}改为key={index}(若数据有唯一标识,也可改用row的唯一字段)
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

