跳至主要内容

useEffect:與外部世界互動的橋樑

什麼是 useEffect?

當組件「渲染後」需要執行動作(如:抓取資料、訂閱事件、修改 DOM),就要用 useEffectuseEffect 讓您在組件「渲染後」執行某些操作。這些操作通常不直接參與畫面繪製,而是與外部世界互動。

核心觀念:

  • 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)

  1. 資料獲取 (Data Fetching):進入頁面後自動從資料庫抓取資料。
  2. 訂閱或事件監聽 (Subscriptions):監聽視窗大小調整圖表。
  3. 手動修改 DOM:使用第三方圖表庫(如 Chart.js)。
  4. 計時器 (Timers):顯示即時更新的時間。

必知細節:清除機制 (Cleanup)

如果您在 useEffect 裡設定了持續性的動作(如 setInterval),當組件被移除(Unmount)時,必須把它清掉,否則會造成記憶體洩漏。

useEffect(() => {
const timer = setInterval(() => {
console.log("定時回傳使用者在線狀態...");
}, 5000);

// 清除函式
return () => {
clearInterval(timer);
console.log("組件卸載,停止計時器");
};
}, []);

useEffect 的三種模式

模式語法執行時機
每次渲染useEffect(() => {})初次掛載 + 每次更新
僅限一次useEffect(() => {}, [])僅初次掛載 (初始化)
條件觸發useEffect(() => {}, [v])初次掛載 + 變數 v 改變時