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

React中Firebase Realtime实现游戏大厅玩家列表更新异常问询

问题根因&修复方案

1. 列表更新延迟/停止更新

根因是监听room_users的useEffect没有配置依赖数组和监听器清理逻辑,每次组件重渲染都会注册新的快照监听器,旧监听器不释放会导致内存泄漏、更新冲突,多次操作后就会出现卡顿、停止更新的问题。
修正后的代码:

const [roomUsers, setRoomUsers] = useState([])

useEffect(() => {
    if (!room) return
    // 获取监听器取消函数
    const unsubscribe = DB.collection("room_users").where("room_id", "==", room.id)
        .onSnapshot((querySnapshot) => {
            const newRoomUsers = [];
            querySnapshot.forEach((doc) => {
                newRoomUsers.push({...doc.data(), docId: doc.id});
            });
            setRoomUsers(newRoomUsers)
        });
    // 组件卸载/依赖变化时自动清理旧监听器
    return () => unsubscribe()
// 仅当room对象变化时才重新注册监听器
}, [room])

2. 用户名重复展示

根因是两个问题共同导致:

  • 玩家列表渲染时没有给PlayerListItem添加唯一key属性,React默认用数组索引作为key,列表成员变化时会错误复用旧的列表项组件
  • PlayerListItem内部拉取用户数据的useEffect没有配置依赖,组件被复用时不会重新拉取新roomUser对应的用户数据,还是展示旧数据

修正步骤:
第一步,给列表项添加唯一key:

<h4>Players list ({roomUsers.length}/4)</h4>

{roomUsers.map(roomUser => (
   <PlayerListItem
      key={roomUser.uuid}
      roomUser={roomUser}
      owner={roomUser.uuid === room.owner}
   />
))}

第二步,修正PlayerListItem内的拉取逻辑,补充依赖和竞态处理:

const [user, setUser] = useState(null)

useEffect(() => {
    // 防止组件卸载后仍更新state报错
    let isMounted = true
    DB.collection('users').where('uuid', '==', roomUser.uuid).get().then(snapshot => {
        if (!isMounted || snapshot.empty) return
        setUser(snapshot.docs[0].data())
    })
    return () => isMounted = false
// uuid变化时重新拉取对应用户数据
}, [roomUser.uuid])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 10:39:02