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

React中Firestore报Invalid document reference错误的排查与解决

问题分析与解决

你的推测是否正确?

不正确。渲染时调用setScore只是提前暴露了代码中的Firebase API使用错误,并非问题根源。

问题根源

  1. Firestore API 使用错误:
    你在setScore函数中用doc(db, "Leaderboard")作为addDoc的参数,但doc()函数需要的是集合路径+文档ID(路径段数为偶数,比如"Leaderboard/user123"),单独的"Leaderboard"是集合路径,段数为1,不符合文档引用的要求。而addDoc的正确用法是传入集合引用,它会自动生成唯一的文档ID。

  2. useEffect 触发时机不当:
    组件初始渲染时isAnonymous为false,useEffect会立即执行setScore,此时user是空字符串,既不符合业务需求(应该在用户点击登录后才提交分数),还会触发无效的Firebase请求。

解决方案

1. 修正setScore的Firebase调用

将doc(db, "Leaderboard")改为collection(db, "Leaderboard"),因为addDoc需要接收集合引用:

const setScore= async(timeprop, userprop)=>{
    console.log(timeprop, userprop)
    await addDoc(collection(db, "Leaderboard"), {
        name: userprop,
        time: timeprop,
    })
}

2. 调整useEffect的触发逻辑

只在用户完成登录(isAnonymous变为true)且user有有效值时,才提交分数并获取排行榜:

useEffect(()=>{
    // 仅当用户登录且用户名非空时执行操作
    if(isAnonymous && user){
        setScore(time, user)
        getLeaderboard()
    }
}, [isAnonymous, user, time])

3. 优化登录校验(可选)

避免用户提交空用户名,在登录函数中增加校验:

const loginAnonymously = () =>{
    if(!username.trim()){
        alert("请输入用户名")
        return
    }
    setUser(username.trim())
    setIsAnonymous(true)
}

4. 修正排行榜渲染的key(可选)

若存在同名用户,用文档ID作为key更可靠,修改getLeaderboard函数:

async function getLeaderboard(){
    const q = query(collection(db, "Leaderboard"));
    const chacSnapShot =  await getDocs(q);
    // 保留文档ID用于渲染key
    const char = chacSnapShot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
    }));
    setLeaderboard(char)
}

渲染时使用data.id作为key:

<div key={data.id} className="user-container">
    <p className="username">{data.name}</p>
    <p className="userdata">{data.time}</p>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:31:06