快速入門
歡迎來到 React 文件!這個頁面將介紹你每天會用到的 80% 的 React 概念。
你將學習
- 如何建立和巢狀元件
- 如何新增標記和樣式
- 如何顯示資料
- 如何渲染條件和列表
- 如何回應事件並更新畫面
- 如何在元件之間共享資料
建立和巢狀元件
React 應用程式是由元件組成的。元件是 UI(使用者介面)的一部分,具有自己的邏輯和外觀。元件可以小到一個按鈕,也可以大到整個頁面。
React 元件是傳回標記的 JavaScript 函式
function MyButton() {
return (
<button>I'm a button</button>
);
}
現在你已經宣告了 MyButton
,你可以將它巢狀到另一個元件中
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
請注意,<MyButton />
以大寫字母開頭。這就是你如何知道它是一個 React 元件。React 元件名稱必須始終以大寫字母開頭,而 HTML 標籤必須是小寫字母。
看看結果
function MyButton() { return ( <button> I'm a button </button> ); } export default function MyApp() { return ( <div> <h1>Welcome to my app</h1> <MyButton /> </div> ); }
關鍵字 export default
指定檔案中的主要元件。如果你不熟悉某些 JavaScript 語法,MDN 和 javascript.info 提供了很好的參考。
使用 JSX 編寫標記
你在上面看到的標記語法稱為*JSX*。它是可選的,但大多數 React 專案都使用 JSX 以求方便。所有我們推薦用於本地開發的工具都原生支援 JSX。
JSX 比 HTML 更嚴格。你必須關閉像 <br />
這樣的標籤。你的元件也不能傳回多個 JSX 標籤。你必須將它們包裝在一個共享的父元素中,例如 <div>...</div>
或一個空的 <>...</>
包裝器
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
如果你有很多 HTML 要移植到 JSX,可以使用線上轉換器。
新增樣式
在 React 中,你使用 className
指定 CSS 類別。它的作用方式與 HTML class
屬性相同
<img className="avatar" />
然後你在單獨的 CSS 檔案中為它編寫 CSS 規則
/* In your CSS */
.avatar {
border-radius: 50%;
}
React 沒有規定你如何新增 CSS 檔案。在最簡單的情況下,你會在 HTML 中新增一個 <link>
標籤。如果你使用建構工具或框架,請參考其文件以了解如何將 CSS 檔案新增到你的專案中。
顯示資料
JSX 讓您可以在 JavaScript 中放入標記。大括號讓您可以「跳回」JavaScript,以便您可以嵌入程式碼中的一些變數並將其顯示給使用者。例如,這將顯示 user.name
return (
<h1>
{user.name}
</h1>
);
您也可以從 JSX 屬性中「跳入 JavaScript」,但您必須使用大括號而不是引號。例如,className="avatar"
會將 "avatar"
字串作為 CSS 類別傳遞,但 src={user.imageUrl}
會讀取 JavaScript user.imageUrl
變數值,然後將該值作為 src
屬性傳遞
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
您也可以在 JSX 大括號內放入更複雜的表達式,例如,字串串接
const user = { name: 'Hedy Lamarr', imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg', imageSize: 90, }; export default function Profile() { return ( <> <h1>{user.name}</h1> <img className="avatar" src={user.imageUrl} alt={'Photo of ' + user.name} style={{ width: user.imageSize, height: user.imageSize }} /> </> ); }
在上面的例子中,style={{}}
不是特殊語法,而是在 style={ }
JSX 大括號內的普通 {}
物件。當您的樣式取決於 JavaScript 變數時,您可以使用 style
屬性。
條件渲染
在 React 中,沒有用於編寫條件的特殊語法。相反,您將使用與編寫常規 JavaScript 程式碼時相同的技巧。例如,您可以使用 if
陳述式有條件地包含 JSX
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
如果您更喜歡更精簡的程式碼,您可以使用條件 ?
運算子。 與 if
不同,它在 JSX 內部有效
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
當您不需要 else
分支時,您也可以使用較短的 邏輯 &&
語法
<div>
{isLoggedIn && <AdminPanel />}
</div>
所有這些方法也適用於有條件地指定屬性。如果您不熟悉其中一些 JavaScript 語法,您可以始終使用 if...else
。
渲染清單
您將依賴 JavaScript 功能,例如 for
迴圈 和 陣列 map()
函式 來渲染組件清單。
例如,假設您有一個產品陣列
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
在您的組件內,使用 map()
函式將產品陣列轉換為 <li>
項目的陣列
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
請注意 <li>
如何具有 key
屬性。對於清單中的每個項目,您應該傳遞一個字串或數字,以在其兄弟姐妹中唯一地標識該項目。通常,金鑰應該來自您的資料,例如資料庫 ID。如果您稍後插入、刪除或重新排序項目,React 會使用您的金鑰來了解發生了什麼事。
const products = [ { title: 'Cabbage', isFruit: false, id: 1 }, { title: 'Garlic', isFruit: false, id: 2 }, { title: 'Apple', isFruit: true, id: 3 }, ]; export default function ShoppingList() { const listItems = products.map(product => <li key={product.id} style={{ color: product.isFruit ? 'magenta' : 'darkgreen' }} > {product.title} </li> ); return ( <ul>{listItems}</ul> ); }
回應事件
您可以透過在組件內宣告*事件處理常式*函式來回應事件
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
請注意 onClick={handleClick}
結尾沒有括號!不要*呼叫*事件處理常式函式:您只需要*將其傳遞*。當使用者點擊按鈕時,React 將會呼叫您的事件處理常式。
更新畫面
通常,您會希望您的組件「記住」一些資訊並顯示它。例如,也許您想計算按鈕被點擊的次數。要做到這一點,請將*狀態*添加到您的組件中。
首先,從 React 導入 useState
import { useState } from 'react';
現在您可以在組件內宣告一個*狀態變數*
function MyButton() {
const [count, setCount] = useState(0);
// ...
您將從 useState
獲得兩樣東西:目前狀態 (count
) 和允許您更新它的函式 (setCount
)。您可以給它們任何名稱,但慣例是寫成 [某事物, 設定某事物]
。
第一次顯示按鈕時,count
將為 0
,因為您將 0
傳遞給了 useState()
。當您想要更改狀態時,請呼叫 setCount()
並將新值傳遞給它。點擊此按鈕將會增加計數器
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
React 會再次呼叫你的元件函式。這次,count
將會是 1
。然後它會是 2
,依此類推。
如果你多次渲染相同的元件,每個元件都會有自己的狀態。請分別點擊每個按鈕。
import { useState } from 'react'; export default function MyApp() { return ( <div> <h1>Counters that update separately</h1> <MyButton /> <MyButton /> </div> ); } function MyButton() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <button onClick={handleClick}> Clicked {count} times </button> ); }
請注意每個按鈕如何「記住」它自己的 count
狀態,並且不會影響其他按鈕。
使用 Hooks
以 use
開頭的函式稱為 *Hooks*。useState
是 React 提供的內建 Hook。你可以在 API 參考 中找到其他內建 Hooks。你也可以透過組合現有的 Hooks 來編寫自己的 Hooks。
Hooks 比其他函式更具限制性。你只能在元件(或其他 Hooks)的*頂部*呼叫 Hooks。如果你想在條件式或迴圈中使用 useState
,請提取一個新的元件並將其放在那裡。
在元件之間共享數據
在前面的範例中,每個 MyButton
都有其獨立的 count
,並且當每個按鈕被點擊時,只有被點擊的按鈕的 count
會改變。


最初,每個 MyButton
的 count
狀態為 0
。


第一個 MyButton
將其 count
更新為 1
。
但是,你通常需要元件*共享數據並始終一起更新*。
要讓兩個 MyButton
元件顯示相同的 count
並一起更新,你需要將狀態從個別按鈕「向上」移動到包含所有按鈕的最接近的元件。
在此範例中,它是 MyApp
。


最初,MyApp
的 count
狀態為 0
,並向下傳遞給兩個子元件。


點擊時,MyApp
將其 count
狀態更新為 1
,並向下傳遞給兩個子元件。
現在,當你點擊任一按鈕時,MyApp
中的 count
將會改變,這將會改變 MyButton
中的兩個計數。以下是如何在程式碼中表達這一點。
首先,將狀態從 MyButton
*向上移動*到 MyApp
。
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... we're moving code from here ...
}
然後,將狀態從 MyApp
*向下傳遞*到每個 MyButton
,以及共享的點擊處理常式。你可以使用 JSX 大括號將資訊傳遞給 MyButton
,就像你之前對 <img>
等內建標籤所做的一樣。
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
你像這樣傳遞下來的資訊稱為*屬性 (props)*。現在 MyApp
元件包含 count
狀態和 handleClick
事件處理常式,並將*兩者都作為屬性傳遞*給每個按鈕。
最後,更改 MyButton
以*讀取*你從其父元件傳遞的屬性。
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
當你點擊按鈕時,onClick
處理常式會觸發。每個按鈕的 onClick
屬性都設定為 MyApp
內部的 handleClick
函式,因此其中的程式碼會執行。該程式碼會呼叫 setCount(count + 1)
,遞增 count
狀態變數。新的 count
值會作為屬性傳遞給每個按鈕,因此它們都會顯示新的值。這稱為「狀態提升」。透過向上移動狀態,你已在元件之間共享它。
import { useState } from 'react'; export default function MyApp() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <div> <h1>Counters that update together</h1> <MyButton count={count} onClick={handleClick} /> <MyButton count={count} onClick={handleClick} /> </div> ); } function MyButton({ count, onClick }) { return ( <button onClick={onClick}> Clicked {count} times </button> ); }