React 中的列表渲染與key屬性
React 中的列表渲染與 key
屬性
在 React 中,列表渲染是非常常見的需求,通常我們會根據數據生成一組相似的元素。當我們使用 JavaScript 的迴圈來渲染列表時,React 需要能夠唯一識別每個列表項,這時就需要使用 key
屬性來幫助 React 高效地更新和渲染列表。
1. 基本的列表渲染
可以使用 JavaScript 的 map()
方法來迭代數據,並將每個項目轉換成 React 元素。React 會將這些元素渲染為一個列表。
範例:基本列表渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}
export default function App() {
const numbers = [1, 2, 3, 4, 5];
return <NumberList numbers={numbers} />;
}
在這個範例中,我們使用 map()
來生成每個數字對應的 li
元素,並在返回的每個 li
元素中使用了 key
屬性。
2. key
屬性的作用
在列表渲染中,key
屬性是非常重要的,它幫助 React 能夠高效地更新和重繪元素。React 使用 key
來識別哪些元素發生了變化、被添加或被移除。key
應該給每個列表中的元素一個唯一的標識符,通常來自數據本身,比如 ID 或唯一的屬性。
範例:key
的重要性
1
2
3
4
5
6
7
8
9
10
11
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number, index) =>
<li key={index}>{number}</li>
)}
</ul>
);
}
雖然這個範例看似可以正常工作,但使用 index
作為 key
並不是最好的做法。當列表發生變動時(如重新排序、插入或刪除項目),這種情況下的 key
可能會導致 React 誤判元素更新,從而影響效能和導致 UI 異常。
3. 選擇合適的 key
- 唯一性:每個
key
在兄弟元素中必須是唯一的。 - 穩定性:
key
在不同的渲染中應保持一致,以便 React 能夠正確地識別和更新元素。
當列表的元素具有唯一 ID 時,通常應該使用 ID 作為 key
。如果沒有唯一 ID,可以考慮創建或生成一個穩定的唯一值。
範例:使用 ID 作為 key
1
2
3
4
5
6
7
8
9
10
11
12
function TodoList(props) {
const todos = props.todos;
return (
<ul>
{todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
)}
</ul>
);
}
在這裡,我們使用了 todo.id
作為 key
,這是一個唯一且穩定的屬性,因此更適合用於列表渲染。
4. key
並不會傳遞給子組件
需要注意的是,key
並不會自動作為 props
傳遞給子組件。如果子組件需要 key
,需要顯式地傳遞。
範例:key
並不會傳遞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function ListItem(props) {
// 即使父組件有 `key`,子組件中也無法直接訪問它
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()} value={number} />
)}
</ul>
);
}
即使在 NumberList
中給 ListItem
元素提供了 key
屬性,ListItem
本身是無法直接訪問 key
的,key
僅用於 React 內部的追蹤和重繪。
5. 為何不能使用索引作為 key
?
使用索引作為 key
並不是一個推薦的做法,因為當列表中的元素重新排序或有插入、刪除操作時,索引會改變,這樣會導致 React 誤認為列表項目是新的元素,從而可能造成效能問題或 UI 異常。
範例:不推薦使用索引作為 key
1
2
3
4
5
6
7
8
9
10
11
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number, index) =>
<li key={index}>{number}</li>
)}
</ul>
);
}
如果列表內容不會變動或只是靜態展示,使用索引可能沒有太大問題,但如果列表會頻繁變動,應盡量避免使用索引作為 key
。
6. 為元素生成唯一的 key
當列表的元素沒有明確的唯一 ID 時,可以根據具體情況生成唯一的 key
,比如使用 uuid
庫或在範例中創建一個簡單的唯一標識。
範例:使用隨機生成的 key
1
2
3
4
5
6
7
8
9
10
11
12
13
import { v4 as uuidv4 } from 'uuid';
function RandomList(props) {
const items = props.items;
return (
<ul>
{items.map((item) =>
<li key={uuidv4()}>{item}</li>
)}
</ul>
);
}
這裡使用 uuid
庫來生成唯一的 key
,保證列表中的每個項目都有一個穩定的標識符。
總結
- 使用
map()
方法來渲染列表,並確保為每個項目提供唯一的key
。 key
用於幫助 React 追蹤元素的變化,以高效地重新渲染列表。- 應盡量避免使用列表的索引作為
key
,因為這可能導致渲染錯誤和效能問題。 key
並不會作為props
傳遞給子組件,僅供 React 內部使用。- 當列表中的元素沒有唯一的 ID 時,可以考慮使用其他方式生成唯一的
key
。
透過正確使用 key
屬性,React 可以更高效地管理和渲染複雜的列表,並保持應用的性能和正確性。