動態產生多個 React 元件

在前幾篇文章中,我們了解 React 最重要的思維是「元件設計」。它讓我們方便得透過重複利用組合元件,作成一個複雜的應用程式,這樣的開發體驗就如同你小時候疊樂高般。

將複雜的畫面解構為多個單一元件,並將它們組合起來

很多時候,我們的資料都是從伺服器上抓取下來的,並不會寫死在程式中,如 TodoApp 的待辦事項清單:

[
{
“id”: 1,
“content”: “完成教材第一章節”,
“completed”: false
},
{
“id”: 2,
“content”: “構思教材第二章節”,
“completed”: false
},
{
“id”: 3,
“content”: “讀完把成功變成習慣”,
“completed”: false
},
{
“id”: 4,
“content”: “讀完成長駭客行銷”,
“completed”: true
}
]

上面是一個 JSON 格式的資料結構,很常用在前後端的傳輸中。這份 JSON 中有四筆待辦項目,每一筆項目都是一個物件格式,除了記錄項目內容(content),也包括了是否完成(completed)和每筆項目的唯一鍵值(id)。

本章節,我們要解決的問題是

因為這份 JSON 是後端傳送來的,我們在設計 TodoApp 時就必須考量動態的待辦清單,不能寫死在程式中。

這裡給你一個提示:通常我們在設計元件時,可以參考要顯示的資料結構。

因此我們可以設計一個 TodoItem 元件來顯示一筆待辦項目;並且在根據項目的多寡,產生多個相對應的 TodoItem。

學習重點

本章節,我們將學習:

  1. 如何讓清單中的每一筆資料,都對應一個元件
  2. 如何組合動態產生的元件

第一步、先設計待辦項目元件(TodoItem)

我們知道 TodoItem 是我們可以重複使用的元件,因此我們先完成顯示一筆待辦項目的元件。

在上面這一個 TodoItem 元件,我們用了之前所學的 props,讓這個元件可以接收上層元件傳遞進來的項目內容(content)和是否完成(completed)。我們讓這一個元件的職責變得很簡單,接收資料和排版。

第二步、修正待辦清單元件(TodoList)

我們在上一個步驟設計了可以讓每筆待辦項目共用的元件 TodoItem。

而現在,我們將修正 TodoList 元件,讓每一筆資料可以對應到一個 TodoItem 元件,並將它們組合起來:

上面這一個 TodoList 元件,我們使用 props 接收上層元件的給予的待辦清單(todos),你也可以從 defaultProps 和 propTypes 中看得出來,它是陣列格式,且預設值是空的陣列。

而 todos 裡的資料結構,就是我們上面看到從伺服器端抓來的 JSON 格式。

重點在:

this.props.todos.map((todo) => {
return (
<li key={todo.id}>
<TodoItem content={todo.content} completed={todo.completed} />
</li>
);
})
  1. 我們使用了陣列內建的 .map(),將 todos 中的每一筆項目物件轉換成 React element,也就是下面回傳的 <li><TodoItem /></li>。
  2. (todo) => {} 是 ES6 匿名函數的寫法,它相等於 function(todo) {},更多請參考 arrows
  3. 在 <li> 中,我們加了 key 的屬性。這讓 React 知道該元件屬於這筆待辦事項,而不會在下一次渲染(render)時被其他資料重複利用,因此它也必須是該陣列中的唯一值。

第三步、傳遞資料進 TodoList 元件

我們在 TodoApp 中遞進 todos 陣列,假設該陣列是從伺服器中抓來的,先寫死在程式中。

重點整理

回顧上面三個步驟:

  1. 設計 TodoItem 元件,讓每一筆待辦項目共用同一支程式
  2. 修改 TodoList 元件,根據資料動態對應到每一個 TodoItem,並組合它們
  3. 修改 TodoApp 元件,傳遞從伺服器中抓取的待辦清單(todos)

上面這些步驟,都讓我們可以重複利用組合元件,React 最重要的精神也在此了!

下一集預告

下一集,「管理元件的內部狀態」,盡情期待囉。

你應該會想看的

上一篇系列文章

Like what you read? Give Jason Chung a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.