簡體   English   中英

state 更新后陣列 map 的奇怪行為

[英]Weird behavior on array map after state update

希望你們都在當前的氣候下保持良好狀態。 I'm working with Firebase and ReactJS at the moment and have encountered an odd behavior with the state update in react and the array map functionality in JavaScript: The code below shows my logic for listening to updates from the firestore database:

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
      });
    });
}

如您所見,一個數組填充了“內容”信息,僅包含文檔的 ID 和一個包含創建該文檔的時間(以秒為單位)的字段。 這給了我一個數組:

0: {id: "SZ4f0Z27rN2MKgXAlglhZVKDsNpKO6", uploaded: 1586323802}

我需要對這個數組進行排序,所以最近的文檔首先出現,因為 Firebase 不提供這個作為查詢參數(你只能 sortBy 而不能改變方向)我將數組復制到一個新數組,然后循環它而不是以正確的順序獲取所有內容:

const sortedArr = [...this.state.content];
sortedArr.reverse();
/// IN THE RETURN: ///
{sortedArr.map((content, index) => (
   <Content key={index} />
))}

這可以正常工作,沒有任何問題。 我的問題是,現在當一個新元素被添加/一個從 state 數組this.state.content和組件被重新渲染時,我看到一個奇怪的行為,其中最后一個元素,而不是顯示新數據,似乎在復制自己。 請參閱下面的示例時間線: 將新文檔添加到數組的步驟 如您所見,當 Firestore 中添加了新文檔時,上面顯示的代碼會正確觸發,將新的數組元素推送到 state 並重新渲染組件。 對於那些感興趣的人,是的,state 正在正確更新,這是在 state 更新后渲染 function 中記錄的內容:

0: {id: "x07yULTiB8MhR6egT7BW6ghmZ59AZY", uploaded: 1586323587}
1: {id: "SZ4f0Z27rN2MKgXAlglhZVKDsNpKO6", uploaded: 1586323802}

您可以看到索引 1 是新的,它是剛剛添加的文檔。 然后,將其反轉並映射到render()return() function 中,但會導致上圖所示的奇怪行為。 任何可能導致這種情況的幫助都會有很大幫助,我已經把頭撞在牆上一段時間了!

當呈現的數組發生突變(即不穩定)時,使用數組索引作為反應鍵會失敗。 React 看到了新的長度,但是第一個元素的鍵仍然是相同的,所以它可以重新渲染(即使它是新元素)。

相反,請嘗試始終在數據集中使用唯一鍵,例如id屬性。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM