v19.2Latest

渲染列表

您經常會希望從資料集合中顯示多個相似的元件。您可以使用 JavaScript 陣列方法 來操作資料陣列。在本頁中,您將使用 filter()map()與 React 一起過濾並將您的資料陣列轉換為元件陣列。

您將學習
  • 如何使用 JavaScript 的 從陣列渲染元件map()
  • 如何使用 JavaScript 的 僅渲染特定元件filter()
  • 何時以及為何使用 React 鍵值

從陣列渲染資料

假設您有一個內容清單。

這些清單項目之間唯一的區別在於它們的內容,也就是它們的資料。在建置介面時,您經常需要使用不同的資料顯示同一個元件的多個實例:從評論清單到個人資料圖片庫。在這些情況下,您可以將資料儲存在 JavaScript 物件和陣列中,並使用map()filter() 等方法從中渲染元件清單。

以下是一個從陣列生成項目清單的簡短範例:

  1. 資料移至陣列中:
  1. people成員映射到一個新的 JSX 節點陣列,listItems
  1. 從您的元件中返回listItems,並將其包裹在 <ul>中:

結果如下:

請注意上面的沙盒顯示了一個控制台錯誤:

控制台

警告:清單中的每個子項目都應該有一個唯一的「key」屬性。

您將在本頁後續學習如何修復此錯誤。在此之前,讓我們為您的資料添加一些結構。

過濾陣列項目

這些資料可以進一步結構化。

假設您想要一種方法來僅顯示職業為 'chemist'的人。您可以使用 JavaScript 的filter() 方法來僅返回這些人。此方法接收一個項目陣列,將其通過一個「測試」(一個返回 truefalse 的函數),並返回一個僅包含通過測試(返回 true)的項目的新陣列。

您只需要 profession'chemist'的項目。對此的「測試」函數看起來像(person) => person.profession === 'chemist'。以下是將其組合在一起的方法:

  1. 建立一個僅包含「化學家」人員的新陣列,chemists,方法是對people 呼叫 filter(),並以 person.profession === 'chemist'進行篩選:
  1. 現在對chemists進行映射
  1. 最後,從你的元件中回傳 listItems
陷阱

箭頭函式會隱式地回傳緊接在 =>之後的運算式,因此你不需要return陳述式:

然而,如果你的 =>後面跟著一個{ 大括號,你必須明確地寫出return

包含 => {的箭頭函式被稱為具有「區塊主體」。它們允許你撰寫多行程式碼,但你必須自行撰寫return陳述式。如果你忘記了,將不會回傳任何內容!

使用 key 保持清單項目順序

請注意,上面的所有沙盒都在控制台中顯示了一個錯誤:

控制台

警告:清單中的每個子項目都應該有一個唯一的「key」屬性。

你需要為每個陣列項目提供一個key—— 一個字串或數字,能在該陣列的其他項目中唯一識別它:

注意

直接在 map()呼叫內的 JSX 元素總是需要的 key!

Key 告訴 React 每個元件對應到哪個陣列項目,以便稍後進行匹配。如果你的陣列項目可能移動(例如由於排序)、被插入或被刪除,這就變得非常重要。一個精心選擇的key有助於 React 推斷到底發生了什麼,並對 DOM 樹進行正確的更新。

你應該將 key 包含在你的資料中,而不是動態生成它們:

Deep Dive
為每個列表項目顯示多個 DOM 節點

從哪裡獲取你的key

不同的數據來源提供不同的 key 來源:

  • 來自資料庫的數據:如果你的數據來自資料庫,你可以使用資料庫的鍵/ID,它們本質上是唯一的。
  • 本地生成的數據:如果你的數據是在本地生成並持久化的(例如筆記應用中的筆記),請使用遞增計數器、crypto.randomUUID()或在創建項目時使用像uuid 這樣的套件。

key 的規則

  • key 在同層級元素中必須是唯一的。 但是,在 不同陣列中的 JSX 節點使用相同的 key 是可以的。
  • key 不得改變,否則就失去了它們的意義!不要在渲染時生成它們。

為什麼 React 需要 key?

想像一下,如果你桌面上的檔案沒有名稱。相反,你將通過它們的順序來引用它們——第一個檔案、第二個檔案,依此類推。你可能會習慣它,但一旦你刪除一個檔案,就會變得混亂。第二個檔案會變成第一個檔案,第三個檔案會變成第二個檔案,依此類推。

資料夾中的檔案名稱和陣列中的 JSX key 具有相似的目的。它們讓我們能夠在同層級元素中唯一識別一個項目。一個精心選擇的 key 提供的資訊比陣列中的位置更多。即使由於重新排序導致位置 發生變化,key也能讓 React 在其整個生命週期中識別該項目。

陷阱

你可能會想使用項目在陣列中的索引作為其 key。事實上,如果你沒有指定 key,React 就會這麼做。但是,如果插入、刪除項目或陣列被重新排序,你渲染項目的順序會隨時間而改變。使用索引作為 key 通常會導致微妙且令人困惑的錯誤。

同樣地,不要動態生成 key,例如使用key={Math.random()}。這將導致 key 在每次渲染之間永遠無法匹配,從而導致你的所有元件和 DOM 每次都被重新創建。這不僅速度慢,還會丟失列表項目內的任何使用者輸入。相反,請使用基於數據的穩定 ID。

請注意,你的元件不會將 key作為 prop 接收。它僅被 React 本身用作提示。如果你的元件需要一個 ID,你必須將其作為單獨的 prop 傳遞:<Profile key={id} userId={id} />

總結

在本頁中,你學到了:

  • 如何將資料移出元件並放入陣列和物件等資料結構中。
  • 如何使用 JavaScript 的 map()來生成一系列相似的元件。
  • 如何使用 JavaScript 的 filter()來建立過濾項目的陣列。
  • 為何以及如何為集合中的每個元件設定key,以便即使其位置或資料發生變化,React 也能追蹤每個元件。

Try out some challenges

Challenge 1 of 4:Splitting a list in two #

This example shows a list of all people.

Change it to show two separate lists one after another: Chemists and Everyone Else. Like previously, you can determine whether a person is a chemist by checking if person.profession === 'chemist'.