當我們需要渲染多筆資料時,通常會使用陣列的 map()
方法將資料轉換成一系列 React 元件。在這過程中,key
屬性的使用非常重要,原因如下:
key
,React 可以更有效率地進行重新渲染。key
可以降低 DOM 更新的開銷,因為 React 能夠精確地知道哪些元素需要被更新而不是全部重新渲染。key
應該是穩定且唯一的,常見的選擇有資料庫中的 id
。如果沒有穩定的 id
,則不得不使用索引,但這只適用於靜態列表或不會重新排序的情況。key
可能會導致不正確的元件狀態更新,尤其是在列表項目可能增刪或重新排序時。假設我們有一個待辦事項列表,可以這樣使用key:
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => ( // todo 該參數代表陣列中的每一筆資料
// 假設 todo.id 為唯一識別碼
<li key={todo.id}>
{todo.text}
</li>
))}
</ul>
);
}
export default TodoList;
我們再演示其它示範:
假設你有一個包含數字或字串的陣列,你可以使用 map()
方法將每個項目轉換成一個 JSX 元素:
function NumberList() {
const numbers = [1, 2, 3, 4, 5];
return (
<ul>
{numbers.map(number => (
<li key={number}>{number}</li>
))}
</ul>
);
}
export default NumberList;
numbers.map()
將每個數字變為 <li>
元素。key
屬性,這裡使用數字本身作為 key。{}
內,讓 JSX 能夠正確解讀並插入結果。而通常資料來源並非單純數字,而是一組物件,例如待辦事項清單:
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<h3>{todo.title}</h3>
<p>{todo.description}</p>
</li>
))}
</ul>
);
}
export default TodoList;
// App.jsx
import TodoList from "./TodoList.jsx"
function App() {
// 使用範例
const todosData = [
{ id: 1, title: "學習 React", description: "閱讀官方文件和範例程式碼" },
{ id: 2, title: "實作專案", description: "開始一個小型的 React 專案" },
{ id: 3, title: "進階學習", description: "了解 Hooks 和 Context API" }
];
return (
<>
// 在應用中渲染 TodoList
<TodoList todos={todosData} />
</>
);
}
export default App
有時候陣列可能是空的,你可以透過條件渲染來提示使用者:
function MessageList({ messages }) {
if (messages.length === 0) {
return <p>目前沒有訊息</p>;
}
return (
<ul>
{messages.map((message, index) => (
<li key={index}>{message}</li>
))}
</ul>
);
}
有時候你可能需要對資料進行過濾、排序或其他變換,再渲染到 JSX 中。例如,假設你要只顯示已完成的任務:
function CompletedTodos({ todos }) {
// 過濾出已完成的任務
const completed = todos.filter(todo => todo.completed);
return (
<ul>
{completed.map(todo => (
<li key={todo.id}>
<span style={{ textDecoration: "line-through" }}>{todo.title}</span>
</li>
))}
</ul>
);
}
export default CompletedTodos
// App.jsx
import CompletedTodos from "./CompletedTodos.jsx"
function App() {
// 範例資料
const todosData = [
{ id: 1, title: "學習 React", completed: true },
{ id: 2, title: "寫作業", completed: false },
{ id: 3, title: "看影片", completed: true }
];
return (
<>
// 在應用中渲染 CompletedTodos
<CompletedTodos todos={todosData} />
</>
);
}
export default App
filter()
過濾出 completed
為 true 的任務。map()
將結果渲染成列表,並可將已完成的任務標記為刪除線。在一些情況下,你可能需要渲染多層次的資料,例如一個留言串中包含回覆、在TodoList中的每條代辦事項中包含可以刪除的按鈕或其它按鈕。
TodoList項目會在之後的幾章節後再做實現,目前讀者只需要知道相關的邏輯操作。