← Back to list

useEffect 的 Side Effect

在 React 中,useEffect 的 Side Effect(副作用)指的是在組件渲染(Render)過程之外,所有會影響到外部環境、或是與外部系統同步的操作。

YC · 2026-06-02 03:09 · 0 claps · 4.3 min read
#react #side-effects
Open on Medium ↗
Wiki topics: 🌐 · Web Development

useEffect 的 Side Effect

在 React 中,useEffect 的 Side Effect(副作用)指的是在組件渲染(Render)過程之外,所有會影響到外部環境、或是與外部系統同步的操作

React 的核心設計理念是「純函數(Pure Function)」,組件的渲染邏輯應該只負責根據 propsstate 計算出畫面(UI),不應該包含任何其他會改變外部世界的行為。那些不屬於計算 UI 的行為,就是副作用。

如果直接把這些副作用寫在組件的「正文」中,會引發嚴重的效能與邏輯問題:

// ❌ 錯誤示範:不要把副作用直接寫在渲染路徑中
function UserProfile() {
  // 每次組件重新渲染,這個 fetch 就會重新執行一次,造成無窮迴圈或效能災難
  fetch('/api/user').then(res => ...); 

  return <div>...</div>;
}

useEffect 的作用就是作為一個逃生口(Escape Hatch),告訴 React:「請先幫我把畫面渲染好,等畫面真正呈現在螢幕上之後,你再幫我執行這段副作用程式碼。」

React 核心架構可以拆成「渲染過程之內與之外」、「影響外部環境」以及「與外部系統同步」這三個核心概念來深入解讀:

「渲染過程之內」(React 的純淨世界)

在 React 的世界裡,組件的「渲染過程(Render)」是指 React 執行你寫的組件函式,並計算出 HTML 結構(JSX)的過程。

React 要求這個過程必須是「純粹的(Pure)」。就像數學公式 f(x) = y,只要輸入的 propsstate(即 x)相同,算出來的 JSX(即 y)就必須完全一樣。

渲染之內做的事:比對資料、決定畫面要顯示文字 A 還是文字 B、用 map 產生列表。這些純粹是組件內部的「數字遊戲」,不與外界接觸。

「渲染過程之外」與「影響外部環境」

當你的程式碼做了渲染之外的事情,改變了 React 控制不到的地方,就叫影響外部環境。

如果 React 在計算畫面的半路上,你突然去改了瀏覽器的全域狀態,這就是「越界」了。

  • 舉個例子:你的組件在計算要顯示什麼按鈕(渲染之內),這很安全。但如果你在函式本體裡直接寫了 document.title = "新標題",你就是繞過 React,直接去改了瀏覽器分頁的標題(影響外部環境)。
  • 為什麼不行?:因為 React 的渲染可能會因為效能優化而重複執行、中斷或延後。如果你把「改變外界」的行為放在渲染之內,外界就會被搞得很混亂(例如:畫面還沒變,分頁標題已經改了 10 次)。

useEffect 就是為此設計的。它把這些行為搬到「渲染之外」——等 React 把畫面都畫好了、瀏覽器也更新了,才在幕後安全地去執行這些改變外界的動作。

「與外部系統同步(Synchronize with External Systems)」

React 官方在最新文件中強調:Effect 是用來與「非 React 控制的系統」進行同步的工具。

React 只管自己的 stateDOM。但現實開發中,我們常常需要讓 React 的資料與「其他世界」保持一致。這些「其他世界(外部系統)」包括:

  1. 後端伺服器。當組件的 userId 改變時,發送 fetch 請求,讓前端資料與資料庫同步。
  2. 瀏覽器 API。當網頁聊天室開啟時,呼叫 window.addEventListener,讓組件能與瀏覽器的視窗事件同步。
  3. 第三方套件。比如使用非 React 的地圖套件(如 Leaflet)或圖表庫(如 D3.js),當 React 資料變動時,呼叫這些套件的 API 去重畫圖表。

常見的 Side Effect 例子

凡是與 React 畫面渲染無關、需要跟瀏覽器或後端溝通的操作都算,主要包含以下四類:

  1. 發送網路請求:使用 fetchaxios 向後端 API 取得資料。
  2. 操作瀏覽器 API 與 DOM:手動修改 document.title、設定定時器(setInterval/setTimeout)或操作第三方圖表庫。
  3. 建立外部訂閱:開啟 WebSocket 連線、監聽全域事件(如瀏覽器的 window.addEventListener('resize'))。
  4. 記錄日誌(Logging):發送數據到 Google Analytics 等埋點追蹤系統。

副作用的清除機制(Cleanup)

有些副作用是「持續性」的(例如計時器或事件監聽),如果不加以清理,當組件被銷毀時會造成記憶體洩漏(Memory Leak)。因此 useEffect 允許你透過 return 一個函式來執行清除副作用(Cleanup)的動作:

import { useEffect } from 'react';

useEffect(() => {
  // 1. 這裡執行副作用(Side Effect)
  const handleResize = () => console.log(window.innerWidth);
  window.addEventListener('resize', handleResize);

  // 2. 這裡返回清除函式(Cleanup)
  return () => {
    window.removeEventListener('resize', handleResize); // 移除監聽,避免記憶體洩漏
  };
}, []); // 依賴陣列

메타데이터
post_id
fa4ca4d01af9
slug
useeffect-的-side-effect-fa4ca4d01af9
url
https://medium.com/@chao97263/useeffect-%E7%9A%84-side-effect-fa4ca4d01af9
canonical_url
https://medium.com/@chao97263/useeffect-%E7%9A%84-side-effect-fa4ca4d01af9
author_url
https://medium.com/@chao97263
status
ok
fetched_at
2026-06-09 15:37:30