React Lists and Keys

產生一個 React 元素清單 (lists; collections) 就跟操作 JavaScript Array 差不多。

例如:

// 一個正常的 JavaScript Array
const numbers = [1, 2, 3, 4, 5];

// 你可以產生一個 React 元素陣列
// 陣列中每個元素都是一個 React element (JSX)
const listItems = numbers.map((numbers) =>
  <li>{numbers}</li>
);

// 將所有的 <li> 元素都放到 <ul> 元素下面
ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

點我看這個例子的結果

最後顯示到畫面的 HTML:

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

你也可以在 JSX 的 { } 中用 inline 的寫法:

const numbers = [1, 2, 3, 4, 5];

ReactDOM.render(
  <ul>
    {numbers.map((numbers) =>
      <li key={numbers.toString()}>{numbers}</li>
    )}
  </ul>,
  document.getElementById('root')
);

執行上面的例子,你可能有發現在 console 中 React 給你一個警告訊息是:

Warning: Each child in an array or iterator should have a unique 'key' prop.

字面上的意思是,你需要給陣列中的每一個 React 元素一個唯一的編號 (unique key),編號是字串型態,設定在 key 這個屬性上。那為什麼會有這個要求呢?因為 React 需要知道實際上哪個元素是哪一個,React 的 Virtual DOM Diff 演算法才能確定哪些元素是需要在 DOM 中被新增的、哪些是要更新的、哪些是要被刪除的。

React 用 key 在陣列中判斷是不是同一個元素物件。

所以上面的例子應該修正為:

const numbers = [1, 2, 3, 4, 5];

// 為每個 React 元素加上獨一無二的 key 編號
const listItems = numbers.map((numbers) =>
  <li key={numbers.toString()}>{numbers}</li>
);

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

如果每個元素不好想出個編號,或陣列中的元素順序是固定不變的,你也可以利用 map function 的第二個 index 參數像這樣子產生編號:

const todoItems = todos.map((todo, index) =>
  // 利用 map function 的第二個 index 參數
  <li key={index}>
    {todo.text}
  </li>
);

key 編號只需要在同一個陣列清單中是不重複 (unique) 的即可。

key 只會被 React 拿來自己用,不會被傳進元件 props 中喔,如果你需要用到這個 key 值,你需要另外自己傳進去,像是:

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);