状态更新后数组映射上的奇怪行为

时间:2020-04-08 05:59:02

标签: javascript arrays reactjs firebase

希望您在当前的气候下都能保持良好状态! 我目前正在使用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} /> ))} 中获取一个元素并重新渲染该组件时,我看到一种奇怪的行为,即最后一个元素(而不是显示新数据)似乎在复制自己。请在下面查看时间轴示例: Steps of a new document being added to array 如您所见,当在Firestore中添加新文档时,上面显示的代码将正确触发,将新的数组元素推入状态并重新呈现组件。对于那些感兴趣的人,是的,状态是正确更新的,这是状态更新后在render函数中记录的内容:

this.state.content

您可以看到索引1是新的,它是刚刚添加的文档。然后,将其反转,映射到0: {id: "x07yULTiB8MhR6egT7BW6ghmZ59AZY", uploaded: 1586323587} 1: {id: "SZ4f0Z27rN2MKgXAlglhZVKDsNpKO6", uploaded: 1586323802} 的{​​{1}}函数中,但会导致上图中所示的怪异行为。任何可能导致此问题的帮助都将是一个很大的帮助,我已经将头撞墙了一段时间了!

1 个答案:

答案 0 :(得分:2)

当渲染的数组发生突变(即不稳定)时,将数组索引用作react键会失败。 React看到了新的长度,但是第一个元素的密钥仍然相同,因此它可以重新渲染(即使它是新元素)。

尝试始终使用数据集中的唯一键,例如id属性。

{sortedArr.map((content, index) => (
   <Content key={content.id} />
))}