Firebase聊天按日期分组报错:期望DocumentReference却传入数组
按日期分组的Firebase聊天功能报错解决
需求与问题
需要实现按日期分组的聊天功能,基于Firebase后端,数据结构为:
- 集合
chats-> 目标文档(ID示例:2h73gbu3id933jeif883ue9) - 文档内
messages字段格式:[{date: 时间戳, m: [消息对象数组]}]
逻辑要求:
- 若消息属于已有日期分组,在对应
m数组中添加新消息 - 若为新日期,新增一个
{date: 当前时间戳, m: [新消息]}对象
用户编写的代码如下:
const today = new Date(); const currentDay = today.toLocaleDateString("en-US", { weekday: "long" }); const docRef = doc(db, "chats", chat.chatId); const docSnap = await getDoc(docRef); const currentMessages = docSnap.data()?.messages || []; const lastMessageDate = currentMessages.length > 0 && currentMessages[currentMessages.length - 1].date.toDate(); const isSameDay = lastMessageDate && lastMessageDate.toLocaleDateString("en-US", { weekday: "long" }) === currentDay; if (!isSameDay) { await updateDoc(docRef, { messages: arrayUnion({ date: Timestamp.now(), m: [{ uid: currentUser.uid, text: message, isSender: true }], }), }); } else { const updatedItems = [ ...currentMessages[currentMessages.length - 1].m, { uid: currentUser.uid, text: message, isSender: true }, ]; await updateDoc(currentMessages, { messages: arrayUnion({ date: lastMessageDate, m: updatedItems, }), }); }
执行isSameDay为true的逻辑时,出现报错:
'index.tsx:64 Uncaught (in promise) FirebaseError: Expected type 'DocumentReference', but it was: an array'
错误原因
- 参数类型错误:
updateDoc的第一个参数必须是Firebase的DocumentReference对象,但else分支中传入了currentMessages(从文档读取的数组),导致类型不匹配。 - 逻辑错误:用
arrayUnion更新已有日期的消息是错误的,arrayUnion的作用是向数组添加新的独立元素,无法修改数组中已存在对象的属性。
修正后的代码
const today = new Date(); const currentDay = today.toLocaleDateString("en-US", { weekday: "long" }); const docRef = doc(db, "chats", chat.chatId); const docSnap = await getDoc(docRef); const currentMessages = docSnap.data()?.messages || []; const lastMessageDate = currentMessages.length > 0 ? currentMessages[currentMessages.length - 1].date.toDate() : null; const isSameDay = lastMessageDate && lastMessageDate.toLocaleDateString("en-US", { weekday: "long" }) === currentDay; if (!isSameDay) { // 新日期,添加分组 await updateDoc(docRef, { messages: arrayUnion({ date: Timestamp.now(), m: [{ uid: currentUser.uid, text: message, isSender: true }], }), }); } else { // 已有日期,更新对应分组的消息列表 // 复制原数组,避免直接修改原数据 const updatedMessages = [...currentMessages]; // 替换最后一个分组的m数组 updatedMessages[updatedMessages.length - 1] = { ...updatedMessages[updatedMessages.length - 1], m: [ ...updatedMessages[updatedMessages.length - 1].m, { uid: currentUser.uid, text: message, isSender: true } ] }; // 直接更新整个messages数组 await updateDoc(docRef, { messages: updatedMessages }); }
关键修改说明
- 确保
updateDoc始终传入正确的docRef(文档引用) - 对于已有日期的场景,重新构造整个
messages数组,修改最后一个分组的m元素后,直接替换文档中的messages字段 - 避免使用
arrayUnion修改已有元素,改用完全更新数组的方式
内容的提问来源于stack exchange,提问作者user21209760
相关产品推荐
相关产品推荐

