useEffectで最後に1回実行する
useEffect
では、副作用の中で登録したイベントリスナーやタイマー、外部リソースなどをコンポーネントのアンマウント時にクリーンアップすることができます。
基本構文
useEffect(() => {
// 初回 or 依存値の変化時に実行される処理
console.log("🟢 エフェクト実行");
// アンマウント時、または依存値変更前に呼ばれる
return () => {
console.log("🟠 クリーンアップ処理");
};
}, []);
return () => { ... }
は、アンマウント時に1回だけ実行される関数[]
(空の依存配列)付きのときは、「初回だけ処理実行 → アンマウント時にクリーンアップ」の流れになる
イベントリスナーの解除
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
console.log("キー入力:", e.key);
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);
✅ 登録したイベントは必ずクリーンアップで解除することで、メモリリークや重複実行を防げます。
setIntervalやsetTimeoutのクリア
useEffect(() => {
const timer = setInterval(() => {
console.log("一定間隔で実行中");
}, 1000);
return () => {
clearInterval(timer); // ⏱️ タイマーの解放
};
}, []);
setInterval
/setTimeout
も明示的にclearInterval
,clearTimeout
で解放する
依存配列がある場合の注意点
useEffect(() => {
console.log("依存値の変更で再実行");
return () => {
console.log("前回のクリーンアップ");
};
}, [count]);
count
が変化するたびに:- まず前回の
return
でクリーンアップ - 次に
useEffect
本体が再実行される
- まず前回の
APIキャンセルやサブスクリプションの解除などにも使える
useEffect(() => {
const controller = new AbortController();
fetch("/api/data", { signal: controller.signal })
.then(res => res.json())
.then(data => console.log(data));
return () => {
controller.abort(); // ⛔ リクエストキャンセル
};
}, []);