快速入門
歡迎來到 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> ); }