第60章:見張りリスト [state]
この章では、useEffect の「見張りリスト」に [state] を入れたときの動き をしっかり理解していきます ✨
キーワードは 「この値が変わったときだけ、
useEffectを動かす」 です ✅
1️⃣ おさらい:useEffect の基本イメージ 🧠
useEffect は、ざっくり言うとこんな子でした:
-
「画面の見た目」以外の仕事をする子(=副作用)
- 例:コンソールにログを出す、
document.titleを変える、タイマーを動かす など
- 例:コンソールにログを出す、
-
書き方はこんな感じ:
useEffect(() => {
// ここに「副作用」の処理を書く
}, /* ← ここが『見張りリスト』 */);
この 第2引数 に入る配列が「見張りリスト(依存配列)」です。
React はここに入っている値を前回と比べて、変わっていたらもう一度 useEffect を実行します。(react.dev)
2️⃣ 見張りリストの3パターンざっくり比較 👀
まずは全体像をさらっと整理しちゃいましょう:
[]→ 最初の1回だけ(マウント時だけ)実行[state]→stateが変わったときだけ 実行 ← 今日はここ‼️- (第2引数なし) → コンポーネントがレンダーされるたび毎回実行(ほとんど使わない)
今回の主役は [state] です 🎉
3️⃣ 図でイメージ:[count] が変わったときだけ動く 🌈
「ボタンを押して count が変わったときだけ useEffect が走る」という流れを Mermaid で図解してみます 🧩
こんな感じで、React は
「見張りリストに入っている値が変わったかどうか」 を毎回チェックしてくれています ✅
4️⃣ 実験①:カウントが変わったときだけコンソールにログを出す 🧪✨
では、実際にコードを書いて「[count] のときだけ動く」感覚をつかみましょう 💻
🛠 手順
- Vite で作った React + TS プロジェクトを開く
src/App.tsxを開く- 中身をいったん全部消して、次のコードをコピペしてみてください 👇
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
// 👇 ここがこの章の主役!
useEffect(() => {
console.log("🎉 count が変わりました!今の値は:", count);
}, [count]); // ← 「count を見張る」リスト
const handleClick = () => {
setCount(count + 1);
};
return (
<div style={{ padding: "24px", fontFamily: "sans-serif" }}>
<h1>第60章:useEffect の見張りリスト [count] 👀</h1>
<p>count: {count}</p>
<button onClick={handleClick}>
+1するボタン ✨
</button>
<p style={{ marginTop: "16px" }}>
ブラウザの開発者ツール(F12)を開いて、Consoleタブを見てみてね 👇
</p>
</div>
);
}
export default App;
▶ 動かしてみよう
-
ターミナルで
npm run dev -
ブラウザで表示している画面で、
F12またはCtrl + Shift + Iを押して Console タブ を開く -
「+1するボタン ✨」をポチポチする
💡 すると…
-
ページを開いた瞬間:
countの初期値は0なので、1回ログが出る -
ボタンを押して
countが1,2,3… と変わるたびに コンソールに🎉 count が変わりました!今の値は: 1 🎉 count が変わりました!今の値は: 2
…というログが出るはずです ✅
逆に、count を変えない限り、useEffect は実行されません。
これが 見張りリスト [count] の効果 です 🌟
5️⃣ 実験②:他の state が変わっても動かないの?🤔
[count] だけを見張っているので、「別の state」が変わっても useEffect は動きません。
一緒に確かめてみましょう 💪
さっきの App.tsx を、こんな感じで少し書き換えてみます 👇
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
const [name, setName] = useState("");
useEffect(() => {
console.log("✅ count が変わったよ!今の値は:", count);
}, [count]); // ← 見張っているのは count だけ!
const handleCountClick = () => {
setCount(count + 1);
};
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
return (
<div style={{ padding: "24px", fontFamily: "sans-serif" }}>
<h1>useEffect の見張りリスト [count] 実験 🔍</h1>
<section>
<h2>① count ボタン</h2>
<p>count: {count}</p>
<button onClick={handleCountClick}>count を +1 🧮</button>
</section>
<section style={{ marginTop: "24px" }}>
<h2>② 名前入力</h2>
<input
type="text"
value={name}
onChange={handleNameChange}
placeholder="名前を入力してみてね ✏️"
/>
<p>こんにちは、{name || "???"} さん 👋</p>
</section>
</div>
);
}
export default App;
✅ 確認ポイント
countボタンを押したとき → コンソールにログが出る(countが変わるから)nameの入力欄に文字を打ったとき → 画面の表示(「こんにちは、〇〇さん」)は変わるけど → コンソールのログは出ない(nameは見張りリストに入っていないから)
→ つまり、[count] と書いたときは、count が変わったときだけ useEffect が動く、ということが体感できるはずです 🌈
6️⃣ 見張りリストに入れる値のルール&注意点 ⚠️
🔹 基本ルール
-
useEffectの中で使っている「変わりうる値」は、見張りリストに入れるのが基本ルールです。- 例:
props、state、コンポーネント内で定義した関数など(react.dev)
- 例:
-
こうしておくと、その値が変わるたびにちゃんと同期してくれるので、バグが減ります 🪄
🔹 よくある危険パターン:無限ループ 😱
こんな書き方は要注意です:
useEffect(() => {
setCount(count + 1); // ← ここで count を更新
}, [count]); // ← そして count を見張っている
countが変わる →useEffectが動く → 中でsetCountする → またcountが変わる → さらにuseEffectが動く…
という 無限ループ になってしまいます 🌀
こういう場合は、
- 条件付きにする(例:
if (count < 5) { ... }) - そもそも
setCountはボタンのonClickの中だけでやる
など、「本当に useEffect の中で state を変える必要がある?」 を考えてみると安全です 💡
7️⃣ まとめ:[state] をちゃんと使えると超便利 💎
この章で覚えておきたいポイントはこれだけ 🌟
useEffectの第2引数は「見張りリスト(依存配列)」👀[state]と書くと → そのstateが変わったときだけuseEffectが実行される- 別の state が変わっても、見張りリストに入っていなければ
useEffectは動かない - 同じ state を見張りながら、その中で無条件に
setStateすると無限ループになるので注意 🌀
🎓 ミニ練習(宿題)💌
時間があれば、こんな練習もしてみてね ✨
keywordという文字列の state を作って、 入力が変わるたびにuseEffectでconsole.log("検索キーワード:", keyword)を出してみる(見張りリストは[keyword])countが変わったときだけdocument.titleを"count: 〇〇"に変えるuseEffectを書いてみる(見張りリストはもちろん[count])
次の章からは、
[][state]- 依存配列なし
の使い分けを、さらに実戦的に深掘りしていきます 🧪✨
おつかれさま〜!また次の章で会おうね 🐥💻💖