Skip to content

建立 2026-09-15 更新 2026-09-15

useEffect

Effect 用來同步外部系統:抓 API、訂閱、操作不是 React 管的 DOM、設計時器。能在渲染時算出來的值,用普通變數或 useMemo 即可,不必寫 Effect。

基本寫法

import { useEffect, useState } from "react";

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let cancelled = false;

    async function load() {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      if (!cancelled) {
        setUser(data);
      }
    }

    load();
    return () => {
      cancelled = true;
    };
  }, [userId]);

  if (!user) {
    return <p>載入中</p>;
  }
  return <h1>{user.name}</h1>;
}
  • 第二個參數是依賴陣列userId 變了才重跑;寫 [] 表示只在掛載時跑一次。
  • 回傳的函式是清理:元件卸載或下次 Effect 前執行,避免競態把舊請求寫進新畫面。
  • 開發模式加了 StrictMode 時,Effect 可能掛載 → 清理 → 再掛載一次,用來檢查你有沒有寫清理。

漏掉依賴會讓 Effect 讀到過期的 props/state。ESLint 的 react-hooks/exhaustive-deps 就是在抓這個。

什麼時候不要用

想做的事 較適合的做法
依 props/state 算出顯示用字串 渲染時直接算
點按鈕才送出表單 事件處理函式裡 fetch
父傳子資料 props,不要 Effect 再 copy 一份 state
兩個 state 永遠要一起變 合併成一個 state,或在事件裡一次 set

官方特別提醒:看到「state 變了再 set 另一個 state」的 Effect,多半可以改成衍生值或事件處理。見 You Might Not Need an Effect

與資料庫/路由

產品若用 Next.js 等框架,列表資料常在伺服器元件或 loader 裡抓,不一定要自己寫 useEffect + fetch。本頁講的是函式庫本身;選框架後以該框架的資料教學為準。

官方對照:Synchronizing with Effects。Net Ninja 播放清單有逐步拆 useEffect 的短片,見 YouTube 優質教學