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

React+Firebase聊天应用报错:无文档可更新问题求助

问题

我跟着YouTube教程用React和Firebase开发聊天应用,遇到了以下错误:

FirebaseError: No document to update: projects/local-eats-discovery/databases/(default)/documents/userChats/pmTVrOVTm1fVLn7WODarHl2WKir2.

另外需要说明的是,当前用户数据加载有延迟,控制台打印currentUser时,初始渲染为undefined,几秒后才会显示用户数据。相关代码如下:

import { useContext, useEffect, useState } from 'react';

import { db } from '../../Firebase/firebase.config';
import { collection, doc, getDoc, getDocs, query, serverTimestamp, setDoc, updateDoc, where } from 'firebase/firestore';
import { AuthContext } from '../../providers/AuthProviders/AuthProviders';

const SearchUser = () => {
    const [userName, setUserName] = useState('');
    const [user, setUser] = useState(null);
    const [err, setErr] = useState(false);
    const [loding,setLoding] = useState(false)
    const { user: currentUser} = useContext(AuthContext);
    console.log(currentUser?.uid);

   useEffect(() => {
    if (!currentUser) {
        setLoding(true)
    }
    setLoding(false)
   },[currentUser])
   
    const handelSearch = 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 handelKey = (e) => { 
        e.code === 'Enter' && handelSearch();
    }


    const handelSelect = async () => {
        // here chacking the group chats in the firebase is exist or not , if not then creat

        { 
            loding && <span> loading...</span>
        }

        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 chat in chats collection 
                await setDoc(doc(db, 'chats', combinedId), { message: [] });
            }
        
            // Update userChats documents
            await updateDoc(doc(db, 'userChats', currentUser.uid), {
                [combinedId + '.userInfo']: {
                    uid: user.uid,
                    displayName: user.displayName,
                    photoURL: user.photoURL
                },
                [combinedId + '.date']: serverTimestamp()
            });
        
            await updateDoc(doc(db, 'userChats', user.uid), {
                [combinedId + '.userInfo']: {
                    uid: currentUser.uid,
                    displayName: currentUser.displayName,
                    photoURL: currentUser.photoURL
                },
                [combinedId + '.date']: serverTimestamp()
            });
        } catch (err) {
            console.log(err);
        }
    }
    return (
        <div className="py-3 px-2">
            <div className="w-full flex justify-start items-start gap-3">
                <input 
                    type="text" 
                    className="border-gray-300 border-2 w-full px-3 py-2 rounded-md" 
                    onKeyDown={handelKey} 
                    onChange={e => setUserName(e.target.value)}
                />
            </div>

            {err && <span>User not found</span>}
            {user && 
                <div className='flex justify-start items-start gap-3 p-5 drop-shadow-md bg-gray-100 mt-4' onClick={handelSelect}>
                    <div><img src={user?.photoURL} alt="" className='w-20'/></div>
                    <div>
                        <h4 className='text-2xs font-bold'>{user?.displayName}</h4>
                        <p className='text-sm text-gray-500'>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ea harum veniam aspernatur voluptatem ex non ....</p>
                    </div>
                </div>
            }
        </div>
    );
};

export default SearchUser;
解决方案

1. 核心错误:userChats文档不存在

updateDoc仅能更新已存在的Firestore文档,你尝试更新的userChats/{currentUser.uid}文档尚未创建,因此触发报错。

替换原有updateDoc逻辑,改用setDoc并添加merge: true参数——该参数会自动处理文档不存在的情况:若文档不存在则创建,若存在则仅更新指定字段,不会覆盖整个文档:

// 替换handelSelect中更新userChats的两段代码
await setDoc(doc(db, 'userChats', currentUser.uid), {
  [combinedId + '.userInfo']: {
    uid: user.uid,
    displayName: user.displayName,
    photoURL: user.photoURL
  },
  [combinedId + '.date']: serverTimestamp()
}, { merge: true });

await setDoc(doc(db, 'userChats', user.uid), {
  [combinedId + '.userInfo']: {
    uid: currentUser.uid,
    displayName: currentUser.displayName,
    photoURL: currentUser.photoURL
  },
  [combinedId + '.date']: serverTimestamp()
}, { merge: true });

2. 修复用户加载延迟的潜在问题

当前用户数据加载延迟,初始currentUser为undefined,可能导致handelSelect中访问currentUser.uid报错,同时原有加载状态逻辑存在问题:

优化加载状态逻辑

原有useEffect会在设置loading: true后立刻设为false,修改为根据currentUser存在状态直接控制:

useEffect(() => {
  setLoding(!currentUser); // 用户未加载时显示加载中,加载完成后结束
}, [currentUser])

防止未加载完成时触发操作

在handelSelect开头增加校验,避免用户数据未加载完成时执行后续逻辑:

const handelSelect = async () => {
  if (!currentUser || !user) return; // 用户数据未就绪时直接返回

  // 原有逻辑...
}

另外,你在handelSelect函数内写的{ loding && <span> loading...</span> }是无效代码(函数逻辑中无法直接渲染JSX),建议将加载提示放到组件的return结构中,或者用状态控制点击区域的禁用状态。

3. 其他小优化

  • handelSearch中如果查询到多个同名用户,只会将最后一个用户存入state,建议处理为数组展示或提示用户重名情况;
  • 搜索操作可添加loading状态,避免重复点击触发多次查询。

内容的提问来源于stack exchange,提问作者Asif Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:56:06