初學者也能懂!React children 全解析與實戰教學

更新日期: 2025 年 4 月 14 日

在學習 React 的過程中,你可能看過這樣的寫法:

<MyComponent>Hello</MyComponent>

或是這樣的:

<MyComponent />

這兩者到底差在哪?為什麼有的元件可以包東西,有的卻是空的?

關鍵就在於 React 元件的一個特殊屬性:children

children 是 React 元件的內建 props,用來接收你在元件標籤中所夾帶的內容

了解它,能幫助你靈活設計畫面結構、實作插槽(slot)功能,也能讀懂 UI Library(像是 Material UI、Chakra UI、Ant Design)裡的元件使用方式。


理解 children 的基本概念

什麼是 children?React 中最神奇的隱藏 props

在 React 中,當你在一個元件標籤中「包住其他內容」,這些內容就會自動被當成該元件的 props.children

來看一個具體的例子:

<MyComponent>
  Hello
</MyComponent>

你看到的是 HTML-like 的寫法,但在 React 背後,其實這段程式碼會被轉換成 JavaScript 語法,如下所示:

<MyComponent children="Hello" />

這代表:

  • MyComponent 這個元件會收到一個 props 物件
  • 其中的 children 欄位值是字串 "Hello"

換句話說,「children 就是包在元件標籤內的所有內容」。不論是文字、JSX、甚至函式的回傳值,React 都會把它們統一當作 children 傳給元件。

再舉一個稍微複雜一點的例子:

<MyComponent>
  <h1>標題</h1>
  <p>這是一段段落。</p>
</MyComponent>

React 會把 <h1><p> 這兩個元素包成一個陣列,當作 children 傳給 MyComponent。也就是:

<MyComponent children={[
  React.createElement('h1', null, '標題'),
  React.createElement('p', null, '這是一段段落。')
]} />

這也解釋了為什麼你在元件中,只要寫:

function MyComponent({ children }) {
  return <div className="box">{children}</div>;
}

就可以自動渲染裡面包的所有內容。

為什麼常常看不到這種寫法?— 自閉合標籤的背後邏輯

你可能會疑惑:「可是我常看到的元件都長這樣啊?」

<MyComponent />

沒錯,這就是所謂的「自閉合寫法(self-closing tag)」,等同於:

<MyComponent></MyComponent>

它們的意思一樣,差別只在於沒有包任何內容,所以 React 自然就不會把 children 傳入。

也就是說,這兩段程式碼:

<MyComponent />
<MyComponent></MyComponent>

都會被轉換成這樣的 JavaScript:

<MyComponent children={undefined} />

也就是 props.children === undefined

那為什麼會這樣寫?

因為這種寫法的元件,本身就是獨立運作、不需要顯示內部內容的元件,例如:

  • <Logo />:只顯示一張 Logo 圖
  • <Button onClick={...} />:按鈕已經內建樣式與功能,不需要額外內容
  • <LoadingSpinner />:純粹顯示動畫

這些元件不需要 children,自然就不需要包住內容。

小結:有沒有 children,看你怎麼使用元件

元件寫法children 傳入值適用場景
<MyComponent>Hello</MyComponent>"Hello"顯示可變內容、自訂畫面區塊
<MyComponent><div /></MyComponent>React Element插入整段自定畫面
<MyComponent />undefined不需要內部內容的元件

這些基礎邏輯搞懂之後,未來你在閱讀開源 UI 套件、開發可組合元件時,就能更輕鬆理解:

  • 哪裡需要傳入 children
  • 為什麼某些元件沒有 children 也能正常運作
  • 怎麼設計自己的元件,讓它能接收並渲染內部內容

React children 的五大資料型別

React 為了讓元件更具彈性,設計了 children 這個特殊的 props。

而它的強大之處就在於:支援多種資料型別,你幾乎可以將任意內容放在 <MyComponent>...</MyComponent> 中,只要是 React 能理解的格式,它就能正確渲染。

以下我們來一一拆解 React 中 children 常見的五大資料型別與它們的行為。

JSX / React Element(React 元素)

💡 什麼是 React Element?

React Element 是由 JSX 所產生的一種 JavaScript 物件,它描述了一個畫面要長什麼樣子。

React 會根據這個描述來渲染實際的 DOM 元素。

🔍 範例:

<MyComponent>
  <div>Hello</div>
</MyComponent>

這裡的 <div>Hello</div> 就是一個 JSX 寫法,它會被 React 編譯成 JavaScript:

React.createElement('div', null, 'Hello')

📌 小提醒:

  • 所有你看到的 <div>...<h1>...、或 <CustomComponent>...,本質上都是 React Element。
  • 這是 children最常見的型別之一,因為你幾乎會在畫面中放很多區塊式的元素。

字串(string)或數字(number)

你可以直接將純文字或數字當作 children 放進元件中,React 會自動將它們顯示為文字節點。

🔍 範例:

<MyComponent>Hello</MyComponent>
<MyComponent>{123}</MyComponent>

✅ React 會如何處理?

  • "Hello" 會變成一段文字出現在畫面上。
  • 123 也會顯示成「123」這串數字,不需要任何額外處理。

這是實作「標題」、「文字內容」、「計數器數字」等靜態資料最直覺的方式。

📌 小提醒:

  • 如果你放的是數字或字串,不需要用 <span><p> 包起來也可以顯示。
  • React 自動幫你完成文字節點的轉換,非常直觀好用!

陣列(Array)

React 支援將多個元素以陣列的方式一起當作 children 傳遞,React 會逐個渲染每個元素,這種寫法在「動態列表」中特別常見。

🔍 範例:

<MyComponent>
  {[<li key="1">A</li>, <li key="2">B</li>]}
</MyComponent>

React 接收到的是一個包含兩個 <li> 元素的陣列,並會渲染為:

<li>A</li>
<li>B</li>

📌 小提醒:

  • 元素陣列中 每一項都需要一個獨特的 key 屬性,否則 React 會發出警告。
  • 這種語法非常常見於 .map() 的應用中,例如:
const fruits = ['蘋果', '香蕉', '芒果'];

<MyComponent>
  {fruits.map((fruit, index) => (
    <li key={index}>{fruit}</li>
  ))}
</MyComponent>

空值型別:nullfalseundefined

React 對這三個值有一個特別的處理方式:完全忽略它們,不會渲染任何東西,也不會報錯。

這樣的設計讓你可以非常簡單地實作條件渲染(Conditional Rendering)。

🔍 範例 1:直接放入空值

<MyComponent>{null}</MyComponent>
<MyComponent>{false}</MyComponent>
<MyComponent>{undefined}</MyComponent>

畫面上完全不會出現任何東西。

🔍 範例 2:搭配邏輯運算實作條件渲染

<MyComponent>
  {isLogin && <p>歡迎回來</p>}
</MyComponent>
  • isLogin === true 時,會顯示 <p>歡迎回來</p>
  • isLogin === false 時,children 等於 false,畫面不會顯示任何東西。

📌 小提醒:

  • 這是一種「不需要額外 if 判斷」的渲染技巧,讓程式碼更簡潔。
  • 但別忘了 0 是 falsy 值,放進去會被顯示出來!

函式或表達式的執行結果

只要你傳入的是一個 合法的 JavaScript 表達式,並且它的回傳值是 React 支援的型別,React 就能正常渲染它。

🔍 範例:

<MyComponent>
  {getContent()}
</MyComponent>

如果 getContent() 回傳的是:

return <p>這是內容</p>;

React 就會正常渲染這個 <p> 元素。

這也代表你可以依照條件去封裝邏輯,例如:

function getContent() {
  return isLogin ? <p>歡迎回來</p> : null;
}

📌 小提醒:

  • 這種模式讓畫面渲染邏輯與 JSX 結構解耦合,易於維護與測試。
  • 函式中只要回傳 React 支援的型別(JSX、字串、null 等),React 都能正確處理。

小整理:五種合法的 children 類型對照表

類型JSX 寫法React 行為
React Element<MyComponent><div>Hi</div></MyComponent>渲染 <div>Hi</div>
字串 / 數字<MyComponent>Hello</MyComponent><MyComponent>{123}</MyComponent>顯示為文字 Hello 或 123
陣列(含 JSX)<MyComponent>{[<li>1</li>, <li>2</li>]}</MyComponent>每個元素都被渲染
空值型別<MyComponent>{null}</MyComponent>畫面上不渲染任何內容
函式執行結果<MyComponent>{getJSX()}</MyComponent>顯示函式回傳的 JSX 或文字內容

實作與範例,掌握 children 的用途

在上一章中,我們學會了什麼是 children,也知道它是 React 元件中專門用來接收「包在元件標籤內的內容」的特殊 props。

這一章,我們就要實際操作,帶你一步步理解 children 的應用方式、視覺輸出結果,以及它在元件設計中的重要角色。

📦 實際範例:用 children 傳入自訂內容

來看看一個非常簡單的元件定義:

function Box({ children }) {
  return <div className="box">{children}</div>;
}

這個 Box 元件的功能非常單純:它就是在畫面上輸出一個帶有 class="box"<div>,而裡面的內容則是由 props.children 動態決定的。

也就是說,Box 元件的畫面內容,完全取決於你怎麼使用它

使用方式一:單一文字

<Box>
  Hello
</Box>

在這個例子中,我們將字串 "Hello" 作為 children 傳入 Box。React 在渲染時,會把這段文字當成內容放進 <div> 中。

🖨️ 輸出結果:

<div class="box">Hello</div>

✅ 解說:

  • Hello 是一段純文字(primitive string),被自動放入 Box<div> 中。
  • 這種方式常用於靜態標題按鈕文字等情境,簡潔又直覺。

使用方式二:一整段 JSX

<Box>
  <h1>標題</h1>
  <p>這是內容</p>
</Box>

這次,我們不是傳文字,而是傳入一整段包含標題與段落的 JSX 元素。這些元素會一起成為 children,被渲染在 Box 中。

🖨️ 輸出結果:

<div class="box">
  <h1>標題</h1>
  <p>這是內容</p>
</div>

✅ 解說:

  • children 的值會是一個 JSX 陣列,包含 <h1><p> 兩個 React Element。
  • React 會自動幫你把它們逐個渲染出來。
  • 這種方式很適合用在版面排版元件(如 Card、Modal、Section 等)中。

這就是 children 的典型用途

透過 children,我們可以讓元件不再只是「單一功能」的組件,而是可以包裝任意內容、靈活配置畫面結構的容器

它讓我們能夠:

  • 建立「共用樣式但內容不同」的元件模板
  • 組合多個元件在一起,提升重複利用率
  • 實作像插槽(slot)那樣的設計模式

延伸思考:為什麼不用 props 傳內容?

你可能會問:為什麼不直接傳一個 titlecontent props 呢?

當然可以,但 children 提供了更自由、不受限制的結構性內容,不需要定義太多 props。

比較一下:

children

<Card>
  <h1>我是標題</h1>
  <p>我是描述</p>
</Card>

用 props:

<Card title="我是標題" content="我是描述" />
  • props 適合傳單一資料項目(文字、數值)
  • children 適合傳一段複雜結構(多層 HTML、元件、邏輯渲染)

結語

理解 children 不只是為了寫畫面,更是為了寫出有彈性、可組合、可擴充的元件。這是從新手 React 工程師,邁向實戰高手的必經之路。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *