Firebase/React中UpdateDoc更新userChats集合为空问题求助
问题:React+Firebase实时聊天中userChats集合始终为空
我用React开发实时私密聊天功能,搜索用户后,预期会更新Firebase的userChats集合,但该集合一直是空的。已经修改过Firestore规则,问题还是没解决。
相关代码
import React, { useContext, useState } from "react"; import { collection, query, where, getDocs, setDoc, doc, updateDoc, serverTimestamp, getDoc, } from "firebase/firestore"; import { db } from "./firebase.js"; import { AuthContext } from "../context/AuthContext"; const Search = () => { const [username, setUsername] = useState(""); const [user, setUser] = useState(null); const [err, setErr] = useState(false); const { currentUser } = useContext(AuthContext); const handleSearch = async () => { const q = query( collection(db, "users"), where("displayName", "==", username) ); try { const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { setUser(doc.data()); }); } catch (err) { setErr(true); } }; const handleKey = (e) => { e.code === "Enter" && handleSearch(); }; const handleSelect = async () => { //check whether the group(chats in firestore) exists, if not create const combinedId = currentUser.uid > user.uid ? currentUser.uid + user.uid : user.uid + currentUser.uid; try { const res = await getDoc(doc(db, "chats", combinedId)); if (!res.exists()) { //create a chat in chats collection await setDoc(doc(db, "chats", combinedId), { messages: [] }); //create user chats await updateDoc(doc(db, "userChats", currentUser.uid), { [combinedId + ".userInfo"]: { uid: user.uid, displayName: user.displayName, }, [combinedId + ".date"]: serverTimestamp(), }); console.log(user.displayName); await updateDoc(doc(db, "userChats", user.uid), { [combinedId + ".userInfo"]: { uid: currentUser.uid, displayName: currentUser.displayName, }, [combinedId + ".date"]: serverTimestamp(), }); } } catch (err) {} setUser(null); setUsername("") }; return ( <div className="search"> <div className="searchForm"> <input type="text" placeholder="Find a user" onKeyDown={handleKey} onChange={(e) => setUsername(e.target.value)} value={username} /> </div> {err && <span>User not found!</span>} {user && ( <div className="userChat" onClick={handleSelect}> <img src={user.photoURL} alt="" /> <div className="userChatInfo"> <span>{user.displayName}</span> </div> </div> )} </div> ); }; export default Search;
当前Firestore规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read,write: if true; } } }
预期的userChats集合结构
userChats Collection: Document 1 (currentUser.uid): - Chat1 (ID): - userInfo: - uid: (ID of the other user) - displayName: (Name of the other user) - date: (Date of the last message) - Chat2 (ID): - userInfo: - uid: (ID of the other user) - displayName: (Name of the other user) - date: (Date of the last message) Document 2 (another user.uid): - Chat1 (ID): - userInfo: - uid: (ID of the currentUser) - displayName: (Name of the currentUser) - date: (Date of the last message) - Chat3 (ID): - userInfo: - uid: (ID of the other user) - displayName: (Name of the other user) - date: (Date of the last message)
问题排查与修复方案
1. 核心问题:updateDoc无法创建新文档
updateDoc仅能修改已存在的文档,如果userChats下对应用户UID的文档不存在,调用updateDoc不会自动创建它,这是集合为空的主要原因。需要先检查文档是否存在,不存在时用setDoc初始化。
2. 其他优化点
- 搜索时限制结果数量,避免多个匹配用户导致的状态覆盖
- 给错误捕获块添加日志输出,方便排查问题
- 增加用户对象的有效性校验,避免undefined错误
修改后的关键代码
优化handleSearch函数
const handleSearch = async () => { const q = query( collection(db, "users"), where("displayName", "==", username), limit(1) // 只取第一个匹配结果 ); try { const querySnapshot = await getDocs(q); if (querySnapshot.empty) { setErr(true); setUser(null); return; } querySnapshot.forEach((doc) => { setUser(doc.data()); }); setErr(false); } catch (err) { setErr(true); console.error("搜索用户失败:", err); } };
修复handleSelect函数
const handleSelect = async () => { if (!currentUser || !user) return; const combinedId = currentUser.uid > user.uid ? currentUser.uid + user.uid : user.uid + currentUser.uid; try { const chatDocRef = doc(db, "chats", combinedId); const chatDocSnap = await getDoc(chatDocRef); if (!chatDocSnap.exists()) { await setDoc(chatDocRef, { messages: [] }); // 处理当前用户的userChats文档 const currentUserChatRef = doc(db, "userChats", currentUser.uid); const currentUserChatSnap = await getDoc(currentUserChatRef); const chatData = { [combinedId]: { userInfo: { uid: user.uid, displayName: user.displayName, }, date: serverTimestamp(), } }; if (currentUserChatSnap.exists()) { await updateDoc(currentUserChatRef, chatData); } else { await setDoc(currentUserChatRef, chatData); } // 处理对方用户的userChats文档 const otherUserChatRef = doc(db, "userChats", user.uid); const otherUserChatSnap = await getDoc(otherUserChatRef); const otherChatData = { [combinedId]: { userInfo: { uid: currentUser.uid, displayName: currentUser.displayName, }, date: serverTimestamp(), } }; if (otherUserChatSnap.exists()) { await updateDoc(otherUserChatRef, otherChatData); } else { await setDoc(otherUserChatRef, otherChatData); } } } catch (err) { console.error("创建/更新聊天失败:", err); setErr(true); } setUser(null); setUsername(""); };
内容的提问来源于stack exchange,提问作者Roberto Tavarez
相关产品推荐
相关产品推荐

