🐛 はじめに(実務で起きたこと)
業務中にこんなバグに遭遇しました。
- 親コンポーネントでデータをセット
- 子コンポーネントでそのデータを使う
- なのに…
👉 子側で「データがundefined」になる
「親でセットしてるやん…」と思って調査した結果、原因は useEffect の実行順序でした。
🎯 結論
useEffectの挙動はシンプルに言うとこうです
- render(描画)が全部終わったあとに実行される
- useEffectは「子 → 親」の順で実行される
これを知らないと普通にバグります。
🧠 useEffectの基本イメージ
まず大前提は useEffectは「レンダリング後に実行される」
処理の流れ
① render(JSX評価)
② DOM更新(画面反映)
③ useEffect実行
日常イメージで Reactを「レストラン」に例えます
1. Render = 料理を作る
- 親シェフが料理を作る
- 子シェフも料理を作る
2. DOM反映 = 料理をテーブルに出す
3. useEffect = 後片付け or 追加作業
⚠️ 重要:実行順序のクセ
ここが今回の本題です。
コンポーネント構造
Parent
└ Child
実行順序
① Parent render
② Child render
③ Child useEffect
④ Parent useEffect
👉 useEffectは「子 → 親」の順で実行される
これは直感と逆なのでハマります。
実際に「親でセットした値を子で使う」ときに、タイミングがズレてバグになるケースがあります
🐛 実際に起きたバグのパターン
// Parent
useEffect(() => {
setData("OK");
}, []);
// Child
useEffect(() => {
console.log(data); // ← undefinedになる
}, []);
なぜ?
- ChildのuseEffectが先に実行される
- まだParentのuseEffectが実行されていない
- → dataが未セット
💡 正しい理解
useEffectはこう覚えるとシンプル
ルール
-
初回:マウント後に実行
-
再レンダリング時:
- 前回のcleanup
- 新しいeffect実行
🛠 対策
① データはuseEffectに頼らない
// ❌ NG(依存関係がズレる)
useEffect(() => {
setValue(calc(props));
}, [props]);
👉 これは render でやるべき
// ✅ OK
const value = calc(props);
② 依存関係を正しく書く
useEffect(() => {
// dataに依存
}, [data]);
③ 親→子の順序に依存しない設計にする
- Context / propsで渡す
- 状態の責務を整理する
🧾 まとめ
- useEffectは「レンダリング後」に実行される
- 実行順序は「子 → 親」
- この挙動を知らないと普通にバグる
👉 「なんか値がない」系バグはまずここを疑うべき