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
相关产品推荐
相关产品推荐

