我有一份Firebase DocumentReferences列表,我需要获取数据并使用该数据设置状态。
这是我尝试过的:
useEffect(() => {
let x = [];
roomData.players.forEach(
async (playerRef: FirebaseFirestoreTypes.DocumentReference) => {
const playerSnap = await playerRef.get()
x.push(playerSnap.data())
}
);
setPlayers(x)
该列表有2个项目。 状态被设置为3次。一次通常有2个对象。第二次将它设置为一个空数组,并且将其设置为3个仅包含一个对象。
答案 0 :(得分:1)
首先,您忽略了关键部分,它是useEffect的第二个参数,它确定何时调用setPlayers。
第二,异步代码可能未按预期运行,因为x传递给setPlayers时的内容未同步。您无法在forEach中使用async,因为无法等待所有结果。因此,在这种情况下,setPlayers(x)
可能会在x.push(playerSnap.data())
之前被调用。
所以最简单的更改是将useEffect第一个参数重写为
roomData.players.forEach(
async (playerRef: FirebaseFirestoreTypes.DocumentReference) => {
const playerSnap = await playerRef.get();
setPlayers(prevPlayers => [...prevPlayers, playerSnap]);
}
);
这将异步更新播放器。
如果您需要播放器进行同步更新,例如仅更新一次UI,或像Firestore中那样反映播放器的顺序,则必须替换forEach。一种这样的方法是使用简单的for循环顺序获取。另一种方法是构造一个承诺数组并将其提供给Promise.all
。