寫 React 時,可能覺得很自然就直接用 <div>
、<h1>
這些看起來像 HTML 的語法。
但其實,瀏覽器本身並不認識這種寫法。
這種語法叫做 JSX,它是 React 提供的一種方式,讓我們可以更直觀地描述 UI。
JSX(JavaScript XML)是一種 JavaScript 語法擴展。
它讓我們在 React 裡用類似 HTML 的方式描述 UI,寫起來更直觀、可讀性更高。
但是要注意:瀏覽器本身不懂 JSX,它必須先經過 Babel / SWC / esbuild 這類工具編譯,轉換成純 JavaScript,才能執行。
在 React 16 以前,JSX 會被轉譯成 React.createElement(...)
。
function Welcome() {
return <h1>Hello</h1>;
}
const element = <Welcome />;
編譯結果:
function Welcome() {
return React.createElement("h1", null, "Hello");
}
const element = React.createElement(Welcome, null);
👉 因此在那個時期,每個檔案都必須 import React from "react"
,否則 JSX 會無法使用。
從 React 17 開始,引入了 新的 JSX Transform,不再透過 React.createElement
,而是呼叫 react/jsx-runtime
提供的 _jsx
/ _jsxs
。
function Welcome() {
return <h1>Hello</h1>;
}
const element = <Welcome />;
編譯結果:
import { jsx as _jsx } from "react/jsx-runtime";
function Welcome() {
return _jsx("h1", { children: "Hello" });
}
const element = _jsx(Welcome, {});
👉 好處是:
import React
。_jsx
與 React.createElement
的作用相同:都會建立 React element(Virtual DOM 物件)。jsxs
。在 JSX 中可以使用以下的語法:
插入表達式
const name = "Andy";
<h1>Hello, {name.toUpperCase()}!</h1>
👉 只能放 expression,不能放 if
/ for
/ let
,也就是statement / declaration。
條件渲染
{isLogin ? <Dashboard /> : <Login />}
{isAdmin && <button>Delete</button>}
列表渲染
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
⚠️ key
很重要,幫助 React 高效追蹤元素,當 list 有更新內容時 React 可以透過 key 來判斷是否可以 reuse 沒改動過的元素,這樣可以達到最小限度地。
屬性命名差異
class
→ className
for
→ htmlFor
onClick
、tabIndex
)單一根元素
// ❌ 錯誤
return (
<h1>Hello</h1>
<p>World</p>
);
// ✅ 正確
return (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
<p>{{ name: "Andy" }}</p>
→ React 會報錯。React.createElement
→ React 17+ 已經改為 _jsx
/ _jsxs
。Q: JSX 是什麼?
JSX 是一種 JavaScript 的擴展語法,看起來像 HTML。
在 React 16 以前,它會被編譯成React.createElement
。
從 React 17 開始,則會編譯成react/jsx-runtime
的_jsx
函式。
不管是哪一種方式,最後都會產生 React element(Virtual DOM 物件)。JSX 的好處是讓 UI 程式碼更直觀、可讀性更高。
React.createElement
。_jsx
/ _jsxs
。UI = f(state, props)
,JSX 只是幫助我們更直觀地表達這個函數。正確來說,JSX 不一定會產生 V-DOM,Solid 的 preset 已經說明了一切,JSX 也不是 React 專屬的東西,詳情請看 這篇文章