Firebase Cloud Firestore文档ID获取问题:card.id返回undefined怎么办?
Cloud Firestore中card.id返回undefined的解决方法
我在Cloud Firestore中存储任务卡片数据,运行以下代码时,card.id返回undefined:
<View style={styles.container}> {cards.map((card, index) => { console.log(card.id); .. ... <View>
我原本以为Firebase会为每个文档提供唯一ID,请问我需要自行创建id属性,还是有Firebase原生的处理方法?
创建任务的代码
import { View, Text, Button, TextInput, StyleSheet } from "react-native"; import DateTimePicker from "@react-native-community/datetimepicker"; import React, { useState } from "react"; import { collection, addDoc } from "firebase/firestore"; import db from "../database/database"; export const CreateTaskScreen = ({ navigation }) => { const [state, SetState] = useState({ title: "", description: "", date: new Date(), hour: new Date(), }); const [showDatePicker, setShowDatePicker] = useState(false); const [showHourPicker, setShowHourPicker] = useState(false); const SetData = (key, value) => { SetState({ ...state, [key]: value, }); }; async function HandlePress() { await addDoc(collection(db, "tasks"), { title: state.title, description: state.description, date: state.date, hour: state.hour, }); navigation.navigate("TaskScreen"); } const handleDatePress = () => { setShowDatePicker(true); }; const handleHourPress = () => { setShowHourPicker(true); }; const handleHourChange = (event, selectedHour) => { setShowHourPicker(false); if (selectedHour) { const currentHour = new Date(selectedHour); hour = currentHour.getHours(); SetData("hour", hour); } }; const handleDateChange = (event, selectedDate) => { setShowDatePicker(false); if (selectedDate) { const currentDate = new Date(selectedDate); SetData("date", currentDate); } }; return ( <View> <Text>Crear tarea</Text> <TextInput placeholder="Title" onChangeText={(value) => SetData("title", value)} /> <TextInput placeholder="Description" multiline numberOfLines={4} onChangeText={(value) => SetData("description", value)} /> <Button title="Select Date" onPress={handleDatePress} /> {showDatePicker && ( <DateTimePicker style={{ width: 200 }} value={state.date} mode="date" display="default" onChange={handleDateChange} /> )} <Button title="Select Hour" onPress={handleHourPress} /> {showHourPicker && ( <DateTimePicker style={{ width: 200 }} value={state.hour} mode="time" display="default" is24Hour={true} onChange={handleHourChange} /> )} <Button title="Save" onPress={HandlePress} /> </View> ); };
获取数据的useEffect代码
useEffect(() => { const unsubscribe = onSnapshot(collection(db, "tasks"), (querySnapshot) => { const taskList = querySnapshot.docs.map((doc) => doc.data()); setCards(taskList); }); // Return the unsubscribe function to clean up the listener return () => unsubscribe(); }, []);
问题原因及解决方法
问题出在获取数据的环节:你调用doc.data()只拿到了文档的内容字段,而文档的ID是Firestore文档的元数据,不会包含在data()返回的对象里。
不需要自行创建ID,Firebase有原生的处理方式,推荐两种方案:
方案1:获取数据时合并文档ID(推荐)
修改useEffect中的map逻辑,把文档ID和数据合并到同一个对象中:
useEffect(() => { const unsubscribe = onSnapshot(collection(db, "tasks"), (querySnapshot) => { const taskList = querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() })); setCards(taskList); }); return () => unsubscribe(); }, []);
这样处理后,每个card对象就会包含id属性,直接访问card.id就能拿到文档的唯一ID。
方案2:创建文档时手动存储ID(不推荐)
如果一定要把ID存在文档内容里,可以在创建时先生成ID,再写入:
async function HandlePress() { // 先生成文档ID const taskRef = doc(collection(db, "tasks")); await setDoc(taskRef, { id: taskRef.id, title: state.title, description: state.description, date: state.date, hour: state.hour, }); navigation.navigate("TaskScreen"); }
但这种方式没必要,因为Firestore已经维护了文档ID作为元数据,重复存储会增加冗余。
内容的提问来源于stack exchange,提问作者samsamradas
相关产品推荐
相关产品推荐

