什麼是 useEffect?
useEffect 是 React 用來處理 Side Effects(副作用)的 Hook,用於在元件渲染後執行與畫面無直接關係的操作,例如資料抓取或是操作 DOM。
useEffect 基礎語法
- 基本結構:
useEffect(() => { 副作用邏輯 }, [依賴陣列])。 - 依賴陣列:第二個參數決定
effect的觸發時機,控制重新執行的條件。 - 空陣列 []:僅在元件初次掛載 (Mount) 時執行一次。
- 有值陣列 [val]:每當
val變動時重新執行effect。 - 清除函式:在
useEffect內return一個函式,元件卸載或下次 effect 執行前會自動呼叫,用來清除上一次的副作用。
常見錯誤與解決方法
- 在
useEffect內直接修改了被列為依賴的狀態,導致「觸發 → 更新 → 觸發」的無限迴圈。 - 計時器或事件監聽未在
cleanup function中移除,建議一律在return () => {}中呼叫對應的取消方法。
import { useState, useEffect } from "react";
function UserCard({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// 每次 userId 改變時,重置載入與錯誤狀態
setLoading(true);
setError(null);
// 建立 AbortController 實例來控制/取消網路請求
const abortController = new AbortController();
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, {
signal: abortController.signal, // 將 signal 綁定到 fetch 請求
})
.then((res) => {
if (!res.ok) throw new Error("獲取資料失敗");
return res.json(); // 解析 JSON
})
.then((data) => {
setUser(data);
setLoading(false);
})
.catch((err) => {
if (err.name !== "AbortError") {
setError(err.message);
setLoading(false);
}
});
// 當 userId 改變或元件卸載時,取消前一次未完成的請求
return () => {
abortController.abort();
};
}, [userId]); // 依賴 userId,當 userId 改變時重新執行
// 條件渲染
if (loading) return <p>載入中...</p>;
if (error) return <p style={{ color: "red" }}>發生錯誤:{error}</p>;
if (!user) return <p>查無使用者</p>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
export default UserCard;
import "./App.css";
import { useState } from "react";
import UserCard from "./components/UserCard";
const App = () => {
const [userId, setUserId] = useState(1); // 預設顯示 ID 為 1 的使用者
return (
<div>
{/* 點擊按鈕切換 userId,將新值傳入 UserCard 觸發 useEffect 重新抓取 */}
<button onClick={() => setUserId((id) => id + 1)}>
下一位使用者 (目前 ID: {userId})
</button>
<UserCard userId={userId} />
</div>
);
};
export default App;
















