跳至主要内容

83 篇文章 含有標籤「前端」

檢視所有標籤

React Hooks useEffect 入門教學 | w3schools 學習筆記

· 閱讀時間約 3 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在 React 函式型元件中,useEffect 是一個強大且常用的 Hook,用來處理副作用(side effects)。副作用指的是那些不直接涉及元件渲染的操作,例如:發送 API 請求、操作 DOM、設定或清除計時器等。

傳統上,這些操作會在 componentDidMountcomponentDidUpdatecomponentWillUnmount 等生命週期函式中進行,而在函式元件中,useEffect 正是用來統一處理這些行為。


重點摘要

  • useEffect 可以執行副作用操作,例如:抓取資料、設定計時器、監聽事件。
  • 語法格式:useEffect(函式, 依賴陣列)
  • 不提供第二個參數時,useEffect 每次重新渲染都會執行。
  • 傳入空陣列作為第二個參數,則只會在元件初次渲染時執行一次。
  • 若依賴陣列中包含特定的 state 或 props,只要它們改變,副作用就會重新執行。
  • 可以在 useEffect 裡透過回傳一個函式進行資源清除(cleanup),避免記憶體洩漏。

實際範例

範例一:沒有依賴陣列,導致每次渲染都執行

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

function Timer() {
const [count, setCount] = useState(0);

useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
});

return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

問題說明:

  • 每次渲染都會重新執行 useEffect,導致 setTimeout 一直重複,數字不斷累加,非預期行為。

範例二:使用空陣列作為依賴,只執行一次

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

function Timer() {
const [count, setCount] = useState(0);

useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
}, []); // 加上空陣列,只在初始渲染時執行一次

return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

重點:

  • 空陣列表示沒有任何依賴,因此只會在元件掛載時執行一次副作用。

範例三:有依賴變數,根據 count 改變而重新執行

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

function Counter() {
const [count, setCount] = useState(0);
const [calculation, setCalculation] = useState(0);

useEffect(() => {
setCalculation(() => count * 2);
}, [count]); // 每次 count 改變就重新計算

return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>+</button>
<p>Calculation: {calculation}</p>
</>
);
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Counter />);

重點:

  • 依賴陣列中包含 count,因此只要 count 改變,useEffect 就會重新執行,計算新的值。

副作用的清除(Effect Cleanup)

某些副作用,如計時器、訂閱、事件監聽器等,當元件卸載或依賴改變時,應該清除,否則可能會導致記憶體洩漏或非預期行為。

useEffect 中可以回傳一個函式,用來執行清除動作。

範例四:清除計時器

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

function Timer() {
const [count, setCount] = useState(0);

useEffect(() => {
const timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);

return () => clearTimeout(timer); // 清除 timeout
}, []);

return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

說明:

  • setTimeout 被命名為 timer,在 useEffect 的清除函式中使用 clearTimeout(timer) 移除它,避免重複執行。

總結

React 的 useEffect 是處理副作用的主要工具。理解它的運作邏輯、依賴機制與清除策略,能幫助開發者更有效率地控制元件的生命周期與效能。

使用建議:

  • 若副作用只需在元件初次渲染執行,請傳入空陣列。
  • 若需要根據變數變動執行副作用,將其加入依賴陣列中。
  • 若副作用產生了外部資源(如計時器、訂閱等),務必記得清除。

掌握這些原則後,就能更靈活並安全地使用 useEffect,打造高效穩定的 React 應用。

參考文件

  1. React Custom Hooks

React Hooks useState 入門教學 | w3schools 學習筆記

· 閱讀時間約 3 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在 React 函式元件中,useState 是最常用的 Hook 之一,能讓我們在無需使用 class 的情況下新增與管理元件的「狀態」(state)。狀態是指會隨著使用者互動或應用邏輯變化而更新的資料,例如:輸入框的內容、按鈕點擊次數、切換的主題顏色等。


重點摘要

  • useState 是 React 提供的 Hook,用來在函式型元件中儲存與更新狀態。
  • 使用前需先從 react 匯入 useState
  • useState(初始值) 會回傳一個陣列,包含目前的狀態值與更新狀態的函式。
  • 更新狀態請使用 setXXX 函式,不可直接修改狀態變數
  • 可以建立多個 useState 追蹤不同變數,也可使用一個物件整合多個欄位。
  • 若要更新物件或陣列的部分內容,應使用展開運算子(spread operator)來保留其他值。

實際範例

1. 匯入 useState

import { useState } from 'react';

使用時,請確認使用的是具名匯入(named import),useStatereact 模組的一部分。


2. 初始化狀態

function FavoriteColor() {
const [color, setColor] = useState('');
}

color 是目前狀態值;setColor 是修改此狀態的函式;初始值設定為空字串。


3. 讀取狀態並渲染

function FavoriteColor() {
const [color, setColor] = useState('red');

return <h1>My favorite color is {color}!</h1>;
}

此例中,畫面上會顯示 My favorite color is red!,透過 JSX 讀取狀態。


4. 使用按鈕更新狀態

function FavoriteColor() {
const [color, setColor] = useState('red');

return (
<>
<h1>My favorite color is {color}!</h1>
<button type="button" onClick={() => setColor('blue')}>
Blue
</button>
</>
);
}

點擊按鈕時,會透過 setColorcolor 更新為 "blue",畫面也會即時更新。


5. 多個狀態變數

function Car() {
const [brand, setBrand] = useState('Ford');
const [model, setModel] = useState('Mustang');
const [year, setYear] = useState('1964');
const [color, setColor] = useState('red');

return (
<>
<h1>My {brand}</h1>
<p>
It is a {color} {model} from {year}.
</p>
</>
);
}

這種方式使用多個 useState 管理多個欄位,彼此獨立。


6. 使用物件作為單一狀態

function Car() {
const [car, setCar] = useState({
brand: 'Ford',
model: 'Mustang',
year: '1964',
color: 'red',
});

return (
<>
<h1>My {car.brand}</h1>
<p>
It is a {car.color} {car.model} from {car.year}.
</p>
</>
);
}

以物件作為狀態,可集中管理多個欄位,也使程式碼更易維護。


7. 更新物件中的單一欄位

function Car() {
const [car, setCar] = useState({
brand: 'Ford',
model: 'Mustang',
year: '1964',
color: 'red',
});

const updateColor = () => {
setCar((prevState) => {
return { ...prevState, color: 'blue' };
});
};

return (
<>
<h1>My {car.brand}</h1>
<p>
It is a {car.color} {car.model} from {car.year}.
</p>
<button type="button" onClick={updateColor}>
Blue
</button>
</>
);
}

這裡使用展開運算子(...prevState)來保留其他屬性,僅更新 color。若直接使用 setCar({ color: "blue" }),會造成其他屬性遺失。


總結

React 的 useState 是建立互動式 UI 的基礎,能讓我們在函式型元件中管理狀態。透過這個 Hook,我們可以:

  • 初始化與讀取狀態值
  • 透過更新函式改變狀態並重新渲染畫面
  • 使用多個 useState 管理多個資料
  • 或整合為一個物件並使用展開運算子更新部分欄位

熟練掌握 useState 是學會 React 開發不可或缺的第一步。建議初學者透過實作各種小範例來加深理解與記憶。

參考文件

  1. React Custom Hooks

React Hooks 入門教學 | w3schools 學習筆記

· 閱讀時間約 2 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

Hooks 是在 React 16.8 版本中加入的新功能。Hooks 讓你可以在「函式元件(function components)」中使用狀態(state)以及其他 React 功能。因此,自從有了 Hooks 之後,類別元件(class components)通常就不再是必要的了

儘管 Hooks 幾乎取代了類別元件的使用方式,但 React 團隊目前並沒有打算移除 class 元件的支援。


什麼是 Hook?

Hooks 讓我們能夠「掛勾(hook into)」React 的核心功能,例如 狀態管理(state)生命週期方法(lifecycle methods)


範例:

import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';

function FavoriteColor() {
const [color, setColor] = useState('red');

return (
<>
<h1>我最喜歡的顏色是 {color}</h1>
<button type="button" onClick={() => setColor('blue')}>
藍色
</button>
<button type="button" onClick={() => setColor('red')}>
紅色
</button>
<button type="button" onClick={() => setColor('pink')}>
粉紅色
</button>
<button type="button" onClick={() => setColor('green')}>
綠色
</button>
</>
);
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<FavoriteColor />);

在這個範例中,我們透過 useState 這個 Hook 來追蹤應用程式的狀態。

狀態(State):泛指那些會隨著使用者互動或應用邏輯而改變的資料或屬性。

此外,使用 Hook 前必須先從 react 模組中引入對應的函式,例如這裡的 useState


使用 Hook 的三大規則

  1. 只能在 React 的函式元件中呼叫 Hooks
  2. 只能在元件的最上層(Top-level)呼叫,不能寫在 iffor函式中等區塊內
  3. 不能有條件式地呼叫 Hook(例如不能寫在 if 判斷中)

注意:Hooks 無法在 class 類別元件中使用!


自訂 Hook(Custom Hooks)

如果你有一些包含狀態的邏輯(stateful logic),需要在多個元件之間重複使用,這時可以考慮封裝成自訂 Hook,以提升可讀性與重用性。

參考文件

  1. React Custom Hooks

在 React 中使用 Sass 進行樣式設計教學 | w3schools 學習筆記

· 閱讀時間約 3 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在現代前端開發中,維護與管理 CSS 樣式是一項重要任務,尤其當應用程式日益龐大、元件複雜時,單純使用原生 CSS 經常會遇到樣式難以重用、命名衝突等問題。這時候,Sass(Syntactically Awesome Stylesheets)這類 CSS 預處理器便顯得格外實用。Sass 提供變數、巢狀語法、Mixin 等強大功能,有助於讓樣式更具模組化與可維護性。

本篇教學將說明如何在 React 專案中使用 Sass,從安裝、建立樣式檔案、到實際在元件中引用,手把手帶你完成設定。


重點摘要

  • Sass 是什麼:一種 CSS 預處理器,可在瀏覽器載入前編譯成標準 CSS。
  • 安裝方法:可透過 npm i sass 安裝 Sass 至 React 專案中。
  • 副檔名:Sass 檔案使用 .scss 副檔名。
  • 支援變數與函數:可使用 $變數@mixin 等進階語法撰寫樣式。
  • 與 React 整合方式:與 CSS 類似,透過 import './樣式.scss' 導入樣式。

Sass 是什麼?

Sass(Syntactically Awesome Stylesheets)是一種 CSS 的擴充語法,稱為 CSS 預處理器(preprocessor)。Sass 檔案會在伺服器端進行編譯,轉換為標準的 CSS,然後再由瀏覽器載入。

與傳統 CSS 相比,Sass 提供多種程式化的功能,包括:

  • 變數(Variables)
  • 巢狀語法(Nesting)
  • 混合(Mixins)
  • 繼承(Inheritance)

這些功能可以大幅簡化樣式維護與邏輯。


如何在 React 中使用 Sass?

若你使用 vite 建立專案,只需要簡單幾步即可在 React 中整合 Sass。

安裝 Sass

打開終端機,並在 React 專案目錄中執行以下指令:

npm i sass

安裝完成後,即可開始在專案中撰寫與導入 .scss 檔案。


建立 Sass 檔案

建立 .scss 檔案的方式與 CSS 相同,唯一差別是副檔名由 .css 改為 .scss

假設建立一個名為 my-sass.scss 的檔案,其內容如下:

// 定義一個變數
$myColor: red;

// 使用變數設定 h1 的文字顏色
h1 {
color: $myColor;
}

這段 Sass 程式碼定義了一個 $myColor 的變數,並將其應用於 h1 標題文字的顏色。


在 React 元件中使用 Sass

要在 React 元件中使用 Sass,只需像導入 CSS 檔案一樣導入 .scss 檔案即可。

以下是一個完整範例:

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './my-sass.scss'; // 導入 Sass 樣式檔

// 建立一個簡單的元件
const Header = () => {
return (
<>
<h1>Hello Style!</h1>
<p>Add a little style!.</p>
</>
);
};

// 掛載元件到畫面上
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);

只要這樣導入 Sass 檔案,該樣式就會自動被應用到對應的元素上,與原生 CSS 的使用方式幾乎一致。


延伸學習建議

若你對 Sass 有更進一步的興趣,建議深入學習以下主題:

  • Sass Mixin 的建立與使用
  • 巢狀規則與 BEM 命名法結合技巧
  • Sass 的分割與模組化導入(@import / @use)
  • 與 CSS Modules、Styled-components 等工具的比較與選擇

總結

Sass 為 CSS 帶來更多彈性與可維護性,是開發大型 React 應用時的重要利器。配合 vite 的簡單整合方式,即使是初學者也能快速上手。只需幾步就能建立出具備變數與結構邏輯的樣式系統,為專案帶來更清晰、可維護的樣式架構。

無論是個人 Side Project 或是商業應用,學會 Sass 的使用,將大大提升你在前端開發上的效率與品質。

參考文件

  1. React Custom Hooks
  2. React router 官方網站

React 中使用 CSS 的三種方式教學 | w3schools 學習筆記

· 閱讀時間約 4 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在開發 React 應用程式時,樣式的管理與設計是一項不可忽視的重要部分。雖然 React 是一個 JavaScript 函式庫,主要用於建構使用者介面,但它本身並不限制開發者如何為元件加上樣式。React 提供多種整合 CSS 的方法,這篇文章將會深入介紹三種最常見的樣式處理方式:行內樣式(Inline Styling)CSS 樣式表(Stylesheet)以及CSS 模組(CSS Modules),並說明每種方式的使用情境與範例。


重點摘要

  • React 支援使用 JavaScript 對元件進行行內樣式設計。
  • 傳統 CSS 樣式表可以與 React 搭配使用,只需匯入對應檔案。
  • 使用 CSS Modules 可避免樣式名稱衝突,適用於大型專案。

一、行內樣式(Inline Styling)

React 提供以 JavaScript 物件的方式設定行內樣式,這種方式最直接也最簡單,適合少量樣式或動態樣式情境。

實作範例:

const Header = () => {
return (
<>
<h1 style={{ color: 'red' }}>Hello Style!</h1>
<p>Add a little style!</p>
</>
);
};

**注意:**在 JSX 中,JavaScript 表達式必須寫在大括號 {} 內,而行內樣式本身是一個物件,因此需使用雙層大括號 {{}}


屬性名稱需使用 camelCase 命名方式

在 JavaScript 中無法使用帶有連字符(例如 background-color)的 CSS 屬性名稱,因此需轉換為 camelCase,例如:backgroundColor

實作範例:

const Header = () => {
return (
<>
<h1 style={{ backgroundColor: 'lightblue' }}>Hello Style!</h1>
<p>Add a little style!</p>
</>
);
};

使用樣式物件來管理樣式

若樣式較多,可先定義一個樣式物件,再以變數形式傳入 style 屬性中。

const Header = () => {
const myStyle = {
color: 'white',
backgroundColor: 'DodgerBlue',
padding: '10px',
fontFamily: 'Sans-Serif',
};

return (
<>
<h1 style={myStyle}>Hello Style!</h1>
<p>Add a little style!</p>
</>
);
};

二、CSS 樣式表(Stylesheet)

若你偏好將樣式與程式邏輯分離,傳統的 CSS 樣式表仍然是實用的選擇。只需建立 .css 檔案並在元件或主程式中匯入即可。

步驟一:建立 App.css 檔案

/* App.css */
body {
background-color: #282c34;
color: white;
padding: 40px;
font-family: Sans-Serif;
text-align: center;
}

**提示:**檔案名稱可以自由命名,但副檔名需為 .css

步驟二:匯入樣式表

// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './App.css';

const Header = () => {
return (
<>
<h1>Hello Style!</h1>
<p>Add a little style!</p>
</>
);
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);

這種方式與傳統 HTML 開發流程相似,適合簡單專案或共用樣式的情境。


三、CSS Modules

CSS Modules 是一種模組化的 CSS 寫法,每個 CSS 檔案的樣式只作用於匯入該檔案的元件,能有效避免樣式衝突,特別適合大型應用程式或多人協作的開發環境。

步驟一:建立模組化樣式檔案

建立一個名稱為 my-style.module.css 的 CSS 檔案:

/* my-style.module.css */
.bigblue {
color: DodgerBlue;
padding: 40px;
font-family: Sans-Serif;
text-align: center;
}

**注意:**檔案名稱需符合 *.module.css 格式,才能啟用模組功能。

步驟二:在元件中匯入模組

// Car.js
import styles from './my-style.module.css';

const Car = () => {
return <h1 className={styles.bigblue}>Hello Car!</h1>;
};

export default Car;

步驟三:匯入元件至主程式

// index.js
import ReactDOM from 'react-dom/client';
import Car from './Car.js';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car />);

透過這種方式,.bigblue 樣式只會應用於 Car 元件,其他元件不會受到影響。


總結

React 提供靈活的方式來處理樣式,你可以根據專案規模與開發需求選擇最適合的做法:

  • 小型元件或需動態切換樣式 → 行內樣式
  • 簡單專案或共用樣式 → 外部樣式表
  • 中大型專案或多人開發 → CSS Modules

透過良好的樣式管理方式,不僅可以提升 UI 的一致性與可維護性,也讓你能更專注於元件的邏輯設計。

如果你正開始學習 React,建議從行內樣式入手,漸進式學習 CSS Modules,將有助於建立健全的開發習慣與架構。

參考文件

  1. React Custom Hooks
  2. React router 官方網站

提升效能的利器:React.memo 使用入門教學 | w3schools 學習筆記

· 閱讀時間約 4 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在 React 中,當元件的父元件重新渲染時,預設情況下其所有子元件也會一併重新渲染,即便傳入的 props 完全沒變動。這種「不必要的重新渲染」若發生在大型應用中,會導致效能下降,尤其是當某些元件非常複雜、包含大量計算或 DOM 操作時。

為了避免這種情況,React 提供了一個高階元件函式:React.memo。這個函式能讓你記憶元件的輸出結果,當傳入的 props 沒有變更時,React 就會跳過該元件的重新渲染,達到提升效能的效果。


重點摘要

  • React.memo 可讓函式型元件根據 props 的淺層比較決定是否重新渲染
  • 適合用在接收不變 props 的純顯示元件
  • props 為函式、物件、陣列時,注意傳入參考要穩定,否則仍會觸發重新渲染
  • 效能提升明顯的情況:元件內容複雜、資料量大或頻繁更新的應用場景
  • 搭配 useCallbackuseMemo 可進一步優化

問題說明

以下是一個簡單的 React 應用,包含一個計數器與待辦事項列表元件(Todos):

index.js

import { useState } from 'react';
import ReactDOM from 'react-dom/client';
import Todos from './Todos';

const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState(['todo 1', 'todo 2']);

const increment = () => {
setCount((c) => c + 1);
};

return (
<>
<Todos todos={todos} />
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
</div>
</>
);
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Todos.js

const Todos = ({ todos }) => {
console.log('child render');
return (
<>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
</>
);
};

export default Todos;

在這個範例中,每當你點擊「+」按鈕讓 count 增加時,整個 App 元件重新渲染,而 Todos 元件也會一併被重新渲染,即使 todos 陣列完全沒有變更。你可以從 console log 中觀察到 child render 不斷出現。

若這個 Todos 元件變得很複雜,這樣的重新渲染就會造成效能浪費。


解法:使用 React.memo

要解決這個問題,我們可以使用 memoTodos 元件包裝起來,使其只有在 props.todos 變動時才會重新渲染。

修改 Todos.js

import { memo } from 'react';

const Todos = ({ todos }) => {
console.log('child render');
return (
<>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
</>
);
};

export default memo(Todos);

這裡我們引入 memo 並用它包裝元件。這樣一來,只要 todos 的內容沒有改變,Todos 元件就不會重新執行 render。


行為比較與效能提升說明

行為未使用 memo使用 memo
count 變更時重新渲染 Todos不重新渲染 Todos
todos 改變時重新渲染 Todos重新渲染 Todos
效能影響易造成浪費避免不必要更新

延伸說明

  • memo 比較的是 props 的淺層相等性。若傳入的是物件、函式等「參考型資料」,每次 render 都會被視為不同,仍然會觸發重新渲染。
  • 若要避免這種情況,可搭配 useMemouseCallback 讓 props 穩定。
  • memo 並非萬能,只有在元件內容複雜、render 成本高時,才明顯帶來效能優化。過度使用反而會增加記憶體與比較成本。

小結

React.memo 是 React 應用中常見的效能優化技巧之一。透過對 props 進行淺層比較,可以有效避免不必要的子元件重新渲染。當你的應用中包含大量重複渲染的靜態元件或資料時,適時使用 memo 可以大幅提升效能表現。

建議在開發時養成習慣:只有當元件的 props 確實可能不會變動,且 render 成本高時再使用 memo,讓效能優化達到真正效果。

參考文件

  1. React Custom Hooks
  2. React router 官方網站

使用 React Router 實現多頁面導覽功能教學(React Router v6)入門教學 | w3schools 學習筆記

· 閱讀時間約 4 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

React 是一個強大的 JavaScript 函式庫,專門用於建立使用者介面。不過,React 本身並未內建「頁面路由」功能。如果你想要為你的 React 專案加入多個頁面,例如首頁、部落格、聯絡我們頁面等等,就必須引入額外的工具。而在眾多路由解決方案中,React Router 是最受歡迎且廣泛使用的選擇。

本文將帶你從零開始,教你如何在使用 Create React App 建立的專案中導入 React Router,並建立一個基本的多頁面架構。


重點摘要

  • React 本身不包含頁面路由功能
  • React Router 是 React 中最常用的路由套件
  • React Router v6 是目前最新的主要版本
  • 需安裝 react-router-dom 套件來使用瀏覽器路由功能
  • 使用 <BrowserRouter>, <Routes>, <Route> 建立路由結構
  • 使用 <Outlet> 顯示巢狀路由對應的內容
  • 使用 <Link> 而非 <a> 進行頁面內部連結

安裝 React Router

在你的 React 專案根目錄下,打開終端機,執行以下指令安裝 React Router:

npm i -D react-router-dom

如果你是從 React Router v5 升級,建議加入 @latest 旗標:

npm i -D react-router-dom@latest

建立頁面資料夾與基本結構

為了建立多頁面應用,我們需要在 src 資料夾中新增一個 pages 資料夾,並在其中建立五個頁面元件:

src/pages/
├── Layout.js
├── Home.js
├── Blogs.js
├── Contact.js
└── NoPage.js

每個檔案都將包含一個簡單的 React 函式元件。


設定主路由(index.js)

src/index.js 中引入路由模組與頁面元件,並建立應用程式主結構:

import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Layout from './pages/Layout';
import Home from './pages/Home';
import Blogs from './pages/Blogs';
import Contact from './pages/Contact';
import NoPage from './pages/NoPage';

export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="blogs" element={<Blogs />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
</BrowserRouter>
);
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

說明範例運作原理

  • <BrowserRouter>:外層包住整個路由結構,提供瀏覽器路由功能。
  • <Routes><Route>:定義所有路由規則與對應的元件。
  • 巢狀 <Route>Layout 元件作為共同外框,其下包含巢狀頁面路由。
  • <Route index>:定義 / 路徑的預設頁面為 Home
  • <Route path="*">:匹配所有未定義的網址,用於顯示 404 頁面。

建立頁面元件

Layout.js(共享頁面結構)

import { Outlet, Link } from 'react-router-dom';

const Layout = () => {
return (
<>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/blogs">Blogs</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>

<Outlet />
</>
);
};

export default Layout;
  • 使用 <Link> 元素建立頁面間的連結。
  • <Outlet> 負責渲染目前選中的頁面內容。

Home.js

const Home = () => {
return <h1>Home</h1>;
};

export default Home;

Blogs.js

const Blogs = () => {
return <h1>Blog Articles</h1>;
};

export default Blogs;

Contact.js

const Contact = () => {
return <h1>Contact Me</h1>;
};

export default Contact;

NoPage.js(404 頁面)

const NoPage = () => {
return <h1>404</h1>;
};

export default NoPage;

總結

透過 React Router,我們可以很輕鬆地為 React 應用程式建立一個多頁面的瀏覽體驗。本篇教學展示了如何安裝 React Router、建立路由結構、撰寫頁面元件,並結合 <Outlet><Link> 實現共用頁面框架與路由切換。這只是入門,React Router v6 還支援更多進階功能,例如動態路由、路由守衛、路由參數等,適合進一步探索使用。

參考文件

  1. React Custom Hooks
  2. React router 官方網站

React 表單入門教學 | w3schools 學習筆記

· 閱讀時間約 4 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

在網頁開發中,表單(Forms)是使用者與網站互動最常見的方式之一。透過表單,我們可以讓使用者輸入資料、提交查詢、填寫訂單等。而在 React 中,表單不再只是簡單的 HTML 元素堆疊,而是成為受控元件(controlled components)的一部分,由 React 元件的 state 負責管理輸入值與提交行為。

本篇教學將帶你一步一步掌握如何在 React 中建立表單、處理輸入變更、提交資料,並涵蓋文字輸入框、多個欄位、Textarea 與 Select 的特殊處理方式,幫助你更靈活地控制資料流程與使用者體驗。


重點摘要

  • 在 React 中,表單輸入值由 component state 管理,稱為「受控元件」。
  • 使用 useState hook 來追蹤每個欄位的變化。
  • 使用 onChange 事件處理輸入值的即時更新。
  • 使用 onSubmit 處理表單送出行為,並透過 event.preventDefault() 阻止預設重新整理頁面的行為。
  • 多個欄位可透過 name 屬性與通用的 handleChange 事件處理函式管理。
  • textareaselect 元素在 React 中透過 value 屬性控制初始與變更的值。

實際範例與說明

一、建立簡單表單

最基本的 React 表單可以像這樣寫:

function MyForm() {
return (
<form>
<label>
Enter your name:
<input type="text" />
</label>
</form>
);
}

雖然這段程式碼可以運作,但在送出表單時會導致頁面刷新。這不是 React 推薦的處理方式。


二、控制輸入欄位(Controlled Components)

我們希望讓 React 完全掌控輸入欄位的狀態,因此需透過 useState 控制值,並在 onChange 事件中更新:

import { useState } from 'react';

function MyForm() {
const [name, setName] = useState('');

return (
<form>
<label>
Enter your name:
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</label>
</form>
);
}

三、處理表單提交

若想處理送出資料而非重新整理頁面,需使用 onSubmit 並加上 preventDefault()

import { useState } from 'react';

function MyForm() {
const [name, setName] = useState('');

const handleSubmit = (event) => {
event.preventDefault();
alert(`您輸入的名字是:${name}`);
};

return (
<form onSubmit={handleSubmit}>
<label>
Enter your name:
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</label>
<input type="submit" />
</form>
);
}

四、多個輸入欄位的管理

當表單中有多個欄位時,使用一個 inputs 物件來集中管理會更加方便:

import { useState } from 'react';

function MyForm() {
const [inputs, setInputs] = useState({});

const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs((values) => ({ ...values, [name]: value }));
};

const handleSubmit = (event) => {
event.preventDefault();
alert(`使用者輸入資料:${JSON.stringify(inputs)}`);
};

return (
<form onSubmit={handleSubmit}>
<label>
Enter your name:
<input type="text" name="username" value={inputs.username || ''} onChange={handleChange} />
</label>
<label>
Enter your age:
<input type="number" name="age" value={inputs.age || ''} onChange={handleChange} />
</label>
<input type="submit" />
</form>
);
}

五、Textarea 的處理方式

在 HTML 中 <textarea> 的值寫在標籤中,但在 React 中,需改為用 value 屬性控制:

import { useState } from 'react';

function MyForm() {
const [textarea, setTextarea] = useState('這裡是預設文字');

const handleChange = (event) => {
setTextarea(event.target.value);
};

return (
<form>
<textarea value={textarea} onChange={handleChange} />
</form>
);
}

六、Select 下拉選單的處理方式

同樣地,<select> 元素的選擇值也應由 value 屬性控制:

import { useState } from 'react';

function MyForm() {
const [myCar, setMyCar] = useState('Volvo');

const handleChange = (event) => {
setMyCar(event.target.value);
};

return (
<form>
<select value={myCar} onChange={handleChange}>
<option value="Ford">Ford</option>
<option value="Volvo">Volvo</option>
<option value="Fiat">Fiat</option>
</select>
</form>
);
}

總結

React 提供一種結構化且一致的方式來處理表單資料,透過 Hook 與事件處理,可以讓應用程式中的資料流更容易掌控與維護。只要掌握好 useStateonChangeonSubmit 等基本技巧,就能在 React 中打造功能完整且具有互動性的表單介面,提升整體使用者體驗與應用穩定性。未來若進一步搭配表單驗證函式庫(如 Formik 或 React Hook Form),可以更加有效率地管理大型與複雜表單邏輯。

參考文件

  1. React Custom Hooks

React List 入門教學 | w3schools 學習筆記

· 閱讀時間約 2 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

React 是一個用於建立 UI 組件的 JavaScript 函式庫,而 JSX 則是 React 中的重要語法擴充。前一章我們已學會如何使用 JSX 編寫 React 介面,本文將進一步說明 React 元件(Components)、props、事件處理(Events)、條件渲染(Conditional Rendering)與列表渲染(Lists)的基本觀念與應用,協助讀者掌握建立互動式介面的核心技巧。

渲染列表與使用 key

基本列表渲染:

function Car(props) {
return <li>I am a {props.brand}</li>;
}

function Garage() {
const cars = ['Ford', 'BMW', 'Audi'];
return (
<>
<h1>Who lives in my garage?</h1>
<ul>
{cars.map((car) => (
<Car brand={car} />
))}
</ul>
</>
);
}

加上 key 改寫版本:

function Car(props) {
return <li>I am a {props.brand}</li>;
}

function Garage() {
const cars = [
{ id: 1, brand: 'Ford' },
{ id: 2, brand: 'BMW' },
{ id: 3, brand: 'Audi' },
];
return (
<>
<h1>Who lives in my garage?</h1>
<ul>
{cars.map((car) => (
<Car key={car.id} brand={car.brand} />
))}
</ul>
</>
);
}

結論 React 提供了彈性而強大的組件機制,透過 props 傳遞資料、事件處理強化互動、條件與列表渲染控制顯示邏輯,讓開發者可以有效建立模組化與資料驅動的使用者介面。熟悉這些基本觀念,將為深入理解 React 的狀態管理與 hooks 打下堅實基礎。

參考文件

  1. React Custom Hooks

React 條件渲染入門教學 | w3schools 學習筆記

· 閱讀時間約 2 分鐘
KD Chang
Maker, Curator & Lifelong learner

前言

React 是一個用於建立 UI 組件的 JavaScript 函式庫,而 JSX 則是 React 中的重要語法擴充。前一章我們已學會如何使用 JSX 編寫 React 介面,本文將進一步說明 React 元件(Components)、props 與事件(Events)的基本觀念與應用,並介紹如何透過函式元件建立互動性的使用者介面,進而引入條件渲染的方式,讓介面能根據資料狀態動態改變內容。

重點摘要

  • React 元件就像函式,會回傳 HTML 元素
  • 元件是可獨立、可重複使用的程式區塊
  • 元件名稱需以大寫開頭
  • props 是元件接收的參數,用來傳遞資料
  • props 是唯讀的,不能在元件內部直接修改
  • 事件處理使用 camelCase 並以大括號包覆事件處理函式
  • 可使用箭頭函式傳遞參數至事件處理器
  • 可透過 if、三元運算子、邏輯運算子 && 實現條件渲染

React 條件渲染

React 提供多種條件渲染的方式,以下為三種常見範例:

  • 使用 if 陳述式:
function MadeGoal() {
return <h1>Goal!</h1>;
}

function MissedGoal() {
return <h1>MISSED!</h1>;
}

function Goal(props) {
const isGoal = props.isGoal;
if (isGoal) {
return <MadeGoal />;
}
return <MissedGoal />;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Goal isGoal={true} />);
  • 使用 && 邏輯運算子:
function Garage(props) {
const cars = props.cars;
return (
<>
<h1>Garage</h1>
{cars.length > 0 && <h2>You have {cars.length} cars in your garage.</h2>}
</>
);
}

const cars = ['Ford', 'BMW', 'Audi'];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Garage cars={cars} />);
  • 使用三元運算子:
function Goal(props) {
const isGoal = props.isGoal;
return <>{isGoal ? <MadeGoal /> : <MissedGoal />}</>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Goal isGoal={false} />);

總結

React 元件是建構 UI 的基本單位,透過 props 傳遞資料與事件處理建立互動,並透過條件渲染控制顯示邏輯。這些基礎觀念為日後深入學習狀態管理、Hooks 與表單處理等主題奠定堅實基礎。

參考文件

  1. React Custom Hooks