JSX 中如何插入 JavaScript?使用 {} 的基本原則

更新日期: 2025 年 3 月 30 日

當你開始學習 React 時,一定會遇到 JSX(JavaScript XML)這個概念。

它看起來像 HTML,卻不完全是 HTML,因為它的背後其實是 JavaScript!

JSX 允許你在畫面中以 HTML 語法描述 UI,同時,也能靈活地插入 JavaScript 程式碼,讓畫面根據資料動態變化。

但初學者常常會有疑問:我要怎麼在 JSX 裡插入 JavaScript 的變數、條件、函式呢? 答案是使用大括號 {}

本文將詳細介紹這個用法,幫助你更自在地在 JSX 中操控 JavaScript 表達式。


基本原則:使用 {} 插入 JavaScript 表達式

在 JSX 中,只要你想在畫面上顯示 JavaScript 的值、運算結果或邏輯判斷,都必須使用大括號 {} 包住這段程式碼。

這個設計讓你可以在 HTML-like 的語法中靈活地動態顯示資料,或是根據程式邏輯控制畫面內容。

什麼可以放進 {}

可以放的是 JavaScript 表達式(expression),而不是語句(statement)。

表達式 是會「產生一個值」的程式碼片段,例如:變數、運算、函式呼叫、三元運算子、陣列、物件等。

語句 則是做事情的程式碼,例如:if 判斷式、for 迴圈、while 等,這些不能放進 {}

舉個最簡單的例子,插入變數:

const name = '小明';

return <h1>Hello, {name}!</h1>;

輸出會是:

<h1>Hello, 小明!</h1>

❌ 錯誤示範:放入語句(statement)

// 錯誤的寫法,JSX 不接受 if 語句直接放在 {} 中
return <div>{if (isOk) { return 'OK'; }}</div>;

這段會直接報錯,因為 {} 裡面只能放會產生值的表達式,不能放像 if 這種語句。

✅正確方式:改用表達式

return <div>{isOk ? 'OK' : 'Not OK'}</div>;

這裡的 isOk ? 'OK' : 'Not OK' 是一個表達式,會根據 isOk 的布林值來決定輸出內容,因此可以放進 JSX 裡。

延伸理解:JSX 背後是 React.createElement()

其實 JSX 只是語法糖,寫 JSX 的背後會被轉換成像這樣的原生 JavaScript:

const element = <h1>Hello, {name}!</h1>;

會轉成:

const element = React.createElement('h1', null, `Hello, ${name}!`);

這就是為什麼只有能產生「值」的表達式能放進去,因為 JSX 的每一個 {} 最終都會變成 React.createElement 的參數值。


插入變數:顯示資料內容

在 JSX 中最基礎、也最常見的用法之一,就是插入變數

當你有一筆資料儲存在變數裡,希望能顯示在畫面上時,就可以使用大括號 {} 把變數包起來,直接插入到你要呈現的地方。

基本範例:將變數插入 HTML 元素中

const age = 18;

return <p>年齡:{age}</p>;

這段程式碼的意思是:建立一個段落 <p>,內容是「年齡:」後面接上變數 age 的值。畫面上看到的結果會是:

年齡:18

🎯 背後邏輯:JSX = JavaScript + 標籤語法

這裡 age 是 JavaScript 中的變數,而 {age} 這段就是一個「JavaScript 表達式」,表示「把 age 的值拿出來插入到這個 <p> 標籤裡」。

由於我們使用 JSX,它可以混合 JavaScript 的語法來描述畫面,因此這樣的插入方式才成為可能。

變數值可以是什麼型別?

你可以插入各種 JavaScript 支援的基本資料型別,只要它們能被「顯示」在畫面上:

資料型別能否插入 JSX?說明
字串 string✅ 可以最常見,例如名字、標題、說明文字等
數字 number✅ 可以用來顯示價格、年齡、數量等
布林值 boolean❌ 不建議直接插入true 或 false 會直接轉成字串顯示,不太直觀
null、undefined❌ 不會顯示任何內容這類值 JSX 會忽略,不會渲染
陣列 array✅ 可以,但需搭配 .map() 使用常用來產生清單(會在下一段介紹)
物件 object❌ 不可直接插入JSX 不知道怎麼顯示物件,會報錯

❌ 錯誤示範:插入物件

const user = { name: '小美', age: 20 };

// 錯誤寫法:物件不能直接放進 JSX 中
return <div>{user}</div>;

這樣會造成錯誤,因為 React 無法直接將物件轉為可顯示的內容。

✅ 正確方式應該是取出特定屬性:

return <div>{user.name}{user.age}</div>;

💡 實用小技巧:結合文字與變數

你可以在一段文字中混合變數與固定內容,非常適合用來呈現個人化的訊息:

const name = '小華';
const score = 95;

return <p>{name} 的成績是 {score}</p>;

輸出:

小華 的成績是 95 

延伸應用:插入變數到屬性中

不只是在標籤內容中,你也可以將變數插入到 HTML 標籤的屬性值中,一樣使用 {}

const imgUrl = 'https://example.com/avatar.jpg';

return <img src={imgUrl} alt="使用者大頭貼" />;

這邊的 src={imgUrl} 就是讓 <img> 使用我們定義的變數來當作圖片來源。


插入函式呼叫:顯示運算後的結果

在 JSX 中,不只能插入變數,也可以插入函式的回傳值

這讓我們能夠在畫面中呈現經過邏輯處理、格式化、計算過的結果,而不是單純的靜態資料。

這是讓畫面更「聰明」的重要技巧之一。

基本用法:呼叫一個函式並插入結果

function greet(name) {
  return `你好,${name}`;
}

return <h2>{greet('小華')}</h2>;

在這段程式碼中,我們先定義了一個 greet() 函式,它會接收一個名字並回傳打招呼的字串。

接著,我們在 JSX 裡面使用 {greet('小華')} 呼叫這個函式,並把它的回傳值插入 <h2> 標籤中。結果畫面會顯示:

你好,小華

什麼樣的函式可以插入?

只要是 會回傳值的函式,就可以插入到 JSX 中。

這些回傳值可以是:

回傳型別說明
字串 (string)最常見,用來產生有格式的文字
數字 (number)可用於計算結果、統計數字等
JSX 元素可以回傳整個 <div>...</div> 或其他組件
陣列通常配合 .map() 來動態產生清單
null用來不渲染任何東西(常見於條件渲染)

🔧 範例 1:格式化數值

function formatPrice(price) {
  return `$${price.toFixed(2)}`;
}

const price = 128;

return <p>價格:{formatPrice(price)}</p>;

結果會顯示:

價格:$128.00

這裡的 formatPrice 是一個「邏輯包裝」函式,把原始數字轉換成帶有 $ 且小數兩位的格式,這樣 JSX 裡的內容就能更符合真實情境。

🔧 範例 2:根據條件產生不同畫面

function getStatus(isOnline) {
  return isOnline ? <span style={{ color: 'green' }}>在線</span> : <span style={{ color: 'gray' }}>離線</span>;
}

const isOnline = true;

return <p>狀態:{getStatus(isOnline)}</p>;

結果會渲染為一個彩色文字:「狀態:在線」,且綠色呈現。

這個技巧適用於更複雜的條件顯示,透過函式把「顯示邏輯」與「UI 呈現」做一點區隔,讓主畫面更清爽。

💡補充技巧:函式定義方式很多種

在 React 中,你可以用不同語法定義函式來供 JSX 使用,這裡列出三種常見方式:

1. 傳統函式
function greet(name) {
  return `你好,${name}`;
}
2. 匿名函式配合變數
const greet = function(name) {
  return `你好,${name}`;
};
3. 箭頭函式(React 中最常見)
const greet = (name) => `你好,${name}`;

你可以依照風格或團隊慣例選擇適合的方式。

常見錯誤:沒有 return 或函式沒回傳值

如果你的函式沒有回傳東西,或是少寫 return,插入到 JSX 中時就不會顯示任何內容,或顯示 undefined

function greet(name) {
  console.log(`你好,${name}`);
  // ❌ 沒有 return
}

return <p>{greet('小花')}</p>; // 這裡不會顯示任何文字

✅ 修正方法:

function greet(name) {
  return `你好,${name}`;
}

插入條件運算:動態改變內容

在網頁開發中,我們常常會遇到「根據條件顯示不同畫面」的情境,例如使用者是否登入、有沒有權限、資料是否加載完成等等。

在 JSX 中,我們無法直接使用傳統的 ifswitch 語法(這些屬於語句 statement),但可以使用「條件運算子」與「邏輯運算子」這兩種方式,來實現畫面上的條件渲染。

為什麼不能用 if

這是因為 JSX 的大括號 {} 只能插入「表達式(expression)」,而像 iffor 這些是「語句(statement)」,會造成語法錯誤。

// ❌ 錯誤:不能在 JSX 裡直接用 if
return (
  <div>
    {if (isLoggedIn) { return <p>歡迎回來!</p>; }}
  </div>
);

正確方式 1:使用條件運算子(? :

條件運算子(三元運算子)語法如下:

條件 ? 條件為真時的結果 : 條件為假時的結果

這是一種能夠根據條件「選擇性產生內容」的表達式,非常適合用來插入 JSX 元素。

🔧 範例:根據登入狀態顯示不同訊息

const isLoggedIn = true;

return <p>{isLoggedIn ? '歡迎回來!' : '請先登入'}</p>;
  • isLoggedIntrue,畫面顯示:「歡迎回來!」
  • isLoggedInfalse,畫面顯示:「請先登入」

你也可以插入完整的 JSX 元素,而不只是字串:

const isLoggedIn = false;

return (
  <div>
    {isLoggedIn ? (
      <h2>歡迎進入會員中心</h2>
    ) : (
      <button>點我登入</button>
    )}
  </div>
);

這讓我們可以根據狀態呈現完全不同的元件內容。

正確方式 2:使用邏輯 AND 運算子(&&

當你只想在某個條件成立時顯示某一個內容,不需要處理「否則」的情況時,可以用 && 運算子。

條件 && 要顯示的內容

當條件為 true 時,才會顯示後面的內容;如果是 false,則什麼都不會顯示。

🔧 範例:有權限才顯示按鈕

const hasPermission = true;

return (
  <>
    <h3>功能列表</h3>
    {hasPermission && <button>編輯</button>}
  </>
);

如果 hasPermissiontrue,畫面會顯示按鈕 <button>編輯</button>;如果是 false,畫面就只會看到標題,不會有按鈕。

⚠️ 注意:布林值直接插入可能出現不預期結果

當你使用 && 來做條件顯示時,如果你插入的不是一個「JSX 元素」,而是某個 JavaScript 值(例如變數、數字、字串),它可能會直接被顯示出來,這通常不是你想要的結果。

🔍 例子:

const value = false;

return <p>{true && value}</p>;

這裡 true && value 的結果是 false,因為 && 的運作規則是:

如果前面是 true,回傳後面的值;

如果前面是 false,直接回傳 false,不看後面。

所以實際上這段等於:

return <p>false</p>; // ⛔ 會把 false 當成文字印出來!

這會在畫面上顯示「false」,這通常是錯誤或令人困惑的情況

✅ 解法一:只渲染 JSX 元素

正確的做法是:當你使用 && 時,右邊的值應該是一個「JSX 元素」,也就是像 <p>...</p> 這樣的內容,而不是一般的變數或值。

const shouldShow = true;

return (
  <>
    {shouldShow && <p>這段文字會被顯示</p>}
  </>
);

這樣寫沒問題,因為 <p>...</p> 是合法的 JSX 元素。

✅ 解法二:使用 !! 轉換成布林值

有時候你不確定變數的值是不是布林值(可能是 undefinednull0"" 等),但你只是想檢查「它是不是有值」,這時可以用 !! 強制轉換它為布林值。

🔧 什麼是 !!

這是 JavaScript 裡的一個小技巧:

!!value

等同於:

Boolean(value)

會把任何值轉成 truefalse。轉換規則如下:

原始值!!後的結果
0false
'' (空字串)false
nullfalse
undefinedfalse
falsefalse
其他有內容的值true
🔍 例子:避免渲染出非預期值
const commentCount = 0;

return (
  <>
    {/* 錯誤:會顯示 0 */}
    {commentCount && <p>{commentCount} 則留言</p>}

    {/* 正確:0 是 falsy,這段就不會顯示 */}
    {!!commentCount && <p>{commentCount} 則留言</p>}
  </>
);

第一行因為 commentCount0,它雖然是 falsy,但仍然會被直接印出來;加上 !! 轉成布林值後,畫面上就不會顯示 0,而是完全不顯示這段 <p>

🧠 延伸:條件運算子與邏輯運算子該用哪個?

使用場景建議用法
根據條件「顯示 A 或 B」兩種可能? :(條件運算子)
根據條件「顯示或不顯示某項」&&(邏輯運算子)
需要處理多重條件邏輯抽成函式或組件處理

插入陣列:顯示清單

在實際開發中,我們常常需要根據一組資料清單,動態產生一組畫面內容,例如留言列表、產品卡片、待辦事項、選項按鈕等等。

在 JSX 中,我們通常會使用 JavaScript 的 陣列方法 .map() 來完成這件事,並搭配 {} 插入每一項轉換後的 JSX 元素。

基本範例:用陣列產生 <li> 清單

const fruits = ['蘋果', '香蕉', '芒果'];

return (
  <ul>
    {fruits.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>
);

畫面上會顯示:

  • 蘋果
  • 香蕉
  • 芒果

🎯 map() 是什麼?

.map() 是 JavaScript 陣列的內建方法,作用是:

把原本的陣列「一個一個拿出來」,經過你的函式處理後,「回傳一個新陣列」,每個元素是你轉換後的結果。

在 JSX 裡,我們就讓它回傳「一組 JSX 元素」,例如 <li><div>、自訂元件等等。

🔍 拆解每一行的意思

{fruits.map((item, index) => (
  <li key={index}>{item}</li>
))}
  • fruits.map(...):針對陣列 fruits 中的每一個水果做處理。
  • (item, index):每次處理時,會拿到陣列中的「值」與「索引」。
  • <li>{item}</li>:回傳一個 <li> 元素,把每個水果的名稱顯示出來。
  • key={index}:React 要求你為每個重複渲染的元素指定一個「唯一的 key」,幫助它在更新畫面時更有效率。

🔐 為什麼一定要加 key

React 需要透過 key 來追蹤哪些項目被新增、刪除、重新排序。

如果你不加,React 會發出警告,並且可能導致效能問題或畫面錯亂。

最常見的做法是使用 index(索引值),但如果你有更穩定的 ID(像是資料庫提供的 id),建議使用真正的唯一值來當 key

const users = [
  { id: 'u01', name: '小明' },
  { id: 'u02', name: '小美' },
];

return (
  <ul>
    {users.map(user => (
      <li key={user.id}>{user.name}</li>
    ))}
  </ul>
);

🔁 實用範例:留言清單

const comments = [
  { id: 1, text: '第一則留言' },
  { id: 2, text: '這是第二則' },
  { id: 3, text: 'React 好好玩!' },
];

return (
  <section>
    <h2>留言列表</h2>
    <ul>
      {comments.map(comment => (
        <li key={comment.id}>{comment.text}</li>
      ))}
    </ul>
  </section>
);

這樣就能自動渲染出所有留言,資料一改,畫面也會跟著更新,非常適合「資料驅動 UI」的開發方式。

❌ 常見錯誤 1:忘記加 key

// ⛔ 錯誤:沒有加 key
{items.map(item => <li>{item}</li>)}

這會導致 React 顯示錯誤警告,也可能在重新渲染時出錯。

✅ 解法:永遠記得加上唯一的 key

❌ 常見錯誤 2:直接插入陣列而不是元素

const names = ['Alice', 'Bob', 'Charlie'];

return <div>{names}</div>; // ⛔ 螢幕會顯示:Alice,Bob,Charlie(不會有標籤)

這樣只是把陣列當成字串輸出,並不是你想要的「一個一個包成 HTML 元素」。

✅ 正確方式:

{names.map((name, i) => <p key={i}>{name}</p>)}

延伸技巧:清單項目可以是任何 JSX 元素

你不只可以產生 <li>,還可以是任意的 HTML 結構或自訂元件:

const products = [
  { id: 101, name: '蘋果', price: 30 },
  { id: 102, name: '香蕉', price: 20 },
];

return (
  <div className="product-list">
    {products.map(product => (
      <div key={product.id} className="product-item">
        <h3>{product.name}</h3>
        <p>價格:${product.price}</p>
      </div>
    ))}
  </div>
);

這樣你就能根據資料清單產生整個畫面結構,甚至能封裝成子元件去管理每一項。


注意事項

在使用 JSX 時,雖然它的語法看起來很像 HTML,但實際上它是 JavaScript 的語法延伸,因此有一些「看起來像可以做,但實際上會報錯」的情況,特別需要注意。

第一點:不能在 JSX 中直接使用語句(statement)

JSX 中的 {} 是用來插入 JavaScript「表達式(expression)」的,而不是「語句(statement)」。

🔍 什麼是表達式(expression)?

  • 表達式是會產生「值」的程式碼
  • 例如:變數、運算、函式呼叫、三元運算子(? :
const name = '小明';
const greeting = `你好,${name}`; // ✅ 表達式

❌ 錯誤:語句不能放進 JSX 的大括號中

以下範例會報錯,因為 if 是「語句」:

return (
  <div>
    {if (isOk) { return <p>OK</p>; }}
  </div>
);

這樣會出現語法錯誤,因為 JSX 不接受 {} 中寫控制流程語法(ifforwhileswitch 都不行)。

✅ 正確寫法:改用表達式(像是三元運算子)

你可以使用三元運算子(條件 ? 為真 : 為假)來達成同樣效果:

return (
  <div>
    {isOk ? <p>OK</p> : <p>Not OK</p>}
  </div>
);

這樣寫是合法的,因為 isOk ? ... : ... 是一個完整會回傳值的表達式,可用於 JSX。

✅ 進階方式:將邏輯抽出到函式或外部變數中

如果條件邏輯很複雜,建議不要直接塞在 JSX 裡面,可以這樣寫:

let content;
if (isOk) {
  content = <p>OK</p>;
} else {
  content = <p>Not OK</p>;
}

return <div>{content}</div>;

這樣邏輯與畫面就分開來,程式會更清楚、好維護。


第二點:JSX 與 HTML 的細微差異

雖然 JSX 看起來像 HTML,但其實底層是 JavaScript,因此在語法上會有幾個地方不同,初學者要特別小心。

1. 屬性中插入變數,需要用 {}

在 HTML 中我們寫:

<h1 title="歡迎頁面">Hello</h1>

但在 JSX 中,如果你要插入一個變數當作屬性值,必須這樣寫:

const title = '歡迎頁面';

return <h1 title={title}>Hello</h1>;

因為 JSX 是 JavaScript,這裡的 title={title} 表示把變數 title 的值作為屬性值傳入。

2. class 屬性要寫成 className

因為 class 是 JavaScript 的保留字,JSX 使用 className 來取代 HTML 的 class

return <div className="box">內容</div>;

3. 有些屬性名稱也會不同

HTML 屬性JSX 對應寫法
forhtmlFor
classclassName
tabindextabIndex
maxlengthmaxLength

結語:善用 {},讓你的 JSX 更靈活

學會在 JSX 中正確插入 JavaScript,是寫出靈活互動畫面的第一步。

記住,只能放「表達式」進 {},但你可以利用它做很多事情:顯示變數、呼叫函式、做條件判斷、顯示清單……熟悉這些用法後,你會發現 JSX 雖然看起來像 HTML,但其實比 HTML 更強大!

Similar Posts