希望您在当前的气候下都能保持良好状态! 我目前正在使用Firebase和ReactJS,在react中的状态更新和JavaScript中的数组映射功能中遇到了奇怪的行为。以下代码显示了我侦听Firestore数据库更新的逻辑:
TypeError
如您所见,在数组中填充了“内容”信息,只是文档的ID,而该字段包含创建该文档的时间(以秒为单位)。这给了我一个数组:
listenForContentChanges = async () => {
let content = [];
await db.collection('clients').doc(this.props.client)
.collection('projects').doc(this.props.id)
.collection('content').orderBy('created').onSnapshot(querySnapshot => {
querySnapshot.docChanges().forEach(async change => {
if (change.type === 'added') {
content.push({
id: change.doc.id,
uploaded: change.doc.data().created.seconds
});
}
if (change.type === 'removed') {
content = content.filter(arrayItem => arrayItem.id !== change.doc.id);
}
});
this.setState({
content: content,
addingContent: false
});
});
}
我需要对该数组进行排序,以便最新的文档排在第一位,并且因为Firebase不提供此数组作为查询参数(您只能对sortBy进行更改,而不能更改方向),所以我将数组复制到新数组中,然后循环遍历而是以正确的顺序获取所有内容:
0: {id: "SZ4f0Z27rN2MKgXAlglhZVKDsNpKO6", uploaded: 1586323802}
这没问题,没问题。我的问题是,现在当添加新元素/从状态数组const sortedArr = [...this.state.content];
sortedArr.reverse();
/// IN THE RETURN: ///
{sortedArr.map((content, index) => (
<Content key={index} />
))}
中获取一个元素并重新渲染该组件时,我看到一种奇怪的行为,即最后一个元素(而不是显示新数据)似乎在复制自己。请在下面查看时间轴示例:
如您所见,当在Firestore中添加新文档时,上面显示的代码将正确触发,将新的数组元素推入状态并重新呈现组件。对于那些感兴趣的人,是的,状态是正确更新的,这是状态更新后在render函数中记录的内容:
this.state.content
您可以看到索引1是新的,它是刚刚添加的文档。然后,将其反转,映射到0: {id: "x07yULTiB8MhR6egT7BW6ghmZ59AZY", uploaded: 1586323587}
1: {id: "SZ4f0Z27rN2MKgXAlglhZVKDsNpKO6", uploaded: 1586323802}
的{{1}}函数中,但会导致上图中所示的怪异行为。任何可能导致此问题的帮助都将是一个很大的帮助,我已经将头撞墙了一段时间了!
答案 0 :(得分:2)
当渲染的数组发生突变(即不稳定)时,将数组索引用作react键会失败。 React看到了新的长度,但是第一个元素的密钥仍然相同,因此它可以重新渲染(即使它是新元素)。
尝试始终使用数据集中的唯一键,例如id
属性。
{sortedArr.map((content, index) => (
<Content key={content.id} />
))}