useEffect:與外部世界互動的橋樑
什麼是 useEffect?
當組件「渲染後」需要執行動作(如:抓取資料、訂閱事件、修改 DOM),就要用 useEffect。
useEffect 讓您在組件「渲染後」執行某些操作。這些操作通常不直接參與畫面繪製,而是與外部世界互動。
核心觀念:
- React 的渲染過程應該是純粹的(輸入什麼資料就畫出什麼畫面)。
- 至於「抓取 API 資料」、「設定計時器」或「手動修改 DOM」,這些會干擾渲染的動作,就必須放在
useEffect裡。
語法拆解
useEffect(() => {
// 這裡是要執行的程式碼 (Effect)
return () => {
// 這裡是用於「清除」的程式碼 (Cleanup) - 選填
};
}, [dependencies]); // 相依陣列 (Dependency Array) - 關鍵!
- 第一個參數:一個函式,定義您要做的動作。
- 第二個參數(相依陣列):
- 不傳(省略):每次渲染後都會執行。
- 空陣列
[]:只在組件「第一次掛載(Mount)」後執行一次(類似初始化)。 - 有值的陣列
[count]:只有當count改變時,才會執行。
實戰範例:模擬資料抓取
「進入頁面時,自動載入使用者資料」 codepen 範例
const { useState, useEffect } = React;
function UserDashboard() {
const [data, setData] = useState("載入中...");
const [count, setCount] = useState(0);
// 情境一:組件掛載時初始化 (API 模擬)
useEffect(() => {
console.log("正在模擬抓取 ERP 資料...");
// 模擬 1 秒後獲取資料
setTimeout(() => {
setData("訂單編號:#2026-A101");
}, 1000);
}, []); // 注意:空陣列代表只跑這一次
// 情境二:當特定狀態改變時執行
useEffect(() => {
if (count > 0) {
document.getElementById('title').innerHTML = `這是DOM元素...:${count}`;
}
}, [count]); // 只有 count 變了,才會執行
return (
<div style={{ padding: '20px' }}>
<h1>ERP 控制台</h1>
<p>狀態:{data}</p>
<hr />
<p>目前點擊:{count}</p>
<button onClick={() => setCount(count + 1)}>點擊加 1</button>
</div>
);
}
常見的使用情境 (Best Practices)
- 資料獲取 (Data Fetching):進入頁面後自動從資料庫抓取資料。
- 訂閱或事件監聽 (Subscriptions):監聽視窗大小調整圖表。
- 手動修改 DOM:使用第三方圖表庫(如 Chart.js)。
- 計時器 (Timers):顯示即時更新的時間。
必知細節:清除機制 (Cleanup)
如果您在 useEffect 裡設定了持續性的動作(如 setInterval),當組件被移除(Unmount)時,必須把它清掉,否則會造成記憶體洩漏。
useEffect(() => {
const timer = setInterval(() => {
console.log("定時回傳使用者在線狀態...");
}, 5000);
// 清除函式
return () => {
clearInterval(timer);
console.log("組件卸載,停止計時器");
};
}, []);
useEffect 的三種模式
| 模式 | 語法 | 執行時機 |
|---|---|---|
| 每次渲染 | useEffect(() => {}) | 初次掛載 + 每次更新 |
| 僅限一次 | useEffect(() => {}, []) | 僅初次掛載 (初始化) |
| 條件觸發 | useEffect(() => {}, [v]) | 初次掛載 + 變數 v 改變時 |