第132章:なぜ「ただの関数」じゃダメなの?🤔(フックを使ってるから!)
この章の結論だけ先に言うね👇
フック(useState / useEffect など)を使う関数は、Reactの“ルールの中”で動く必要があるから、ただの関数にしちゃうと事故りやすいのです😵💫💥
だから「カスタムフック」って形(useで始まる関数)にして、安全に再利用できるようにするよ〜✨
1) まず大事:Reactは「フックを呼んだ順番」で覚えてる🧠📌
Reactは、コンポーネントが描画されるたびに 「1個目のフックはこれ」「2個目のフックはこれ」って 順番で状態を管理してるよ!
つまり… ✅ 毎回同じ順番でフックが呼ばれることが超重要!
2) 「ただの関数」にしちゃうと起きがちな事故🚑💥
❌ 事故例:条件分岐の中でフックを呼ぶ(順番がズレる)
import { useState } from "react";
function helper(flag: boolean) {
if (flag) {
const [x] = useState(0); // ❌ これ、順番が変わる可能性がある!
return x;
}
return 0;
}
export function App() {
const a = helper(true);
return <div>{a}</div>;
}
なにがヤバいの?😱
flag が変わった瞬間に 呼ばれるフックの数・順番が変わる → Reactが状態を取り違える可能性💥
3) じゃあ「カスタムフック」って何が偉いの?🌟
カスタムフックは一言でいうと👇 “フックを安全に再利用するための、ルールに乗った関数” だよ🙌✨
✅ カスタムフックにすると得すること
- Reactのルール(同じ順番)を守りやすい🧷
- ESLint が「フックのルール違反」を検知してくれる🔍(超大事!)
- 状態を持つロジックを部品みたいに使い回せる🧩
- 命名が
use〇〇だと「フックっぽい!」って一目でわかる😊
4) ここがポイント:実は「カスタムフックもただの関数」🫢✨
ちょっと意外なんだけど、カスタムフック自体は普通の関数だよ。 でも違いはここ👇
✅ 違いは「ルールに乗ってるか」&「見分けがつくか」
useで始まる → フックだと分かる- ESLintが “ここはフックを呼んでOKな場所” と判断しやすい
- チーム開発でも事故りにくい👯♀️💕
5) 正しい形:カスタムフックにして安全にする🧁
✅ useNumber(例:数を持つだけのシンプルフック)
import { useState } from "react";
export function useNumber(initialValue: number) {
const [value, setValue] = useState(initialValue);
const inc = () => setValue((v) => v + 1);
const dec = () => setValue((v) => v - 1);
return { value, inc, dec };
}
使う側(コンポーネント)はこう👇
import { useNumber } from "./useNumber";
export function App() {
const { value, inc, dec } = useNumber(10);
return (
<div>
<p>いま:{value}</p>
<button onClick={dec}>-1</button>
<button onClick={inc}>+1</button>
</div>
);
}
これなら ✅ フックはコンポーネントのトップレベルで毎回同じ順番で呼ばれる ✅ しかもロジックを再利用できる 最高〜〜〜!🎉😆
6) 「フックのルール」最低限これだけ覚えよ📚✨
覚え方(ゆるく)👇
- フックは毎回同じ順で呼ぶ🧘♀️
- フックは“特別な場所”でだけ呼ぶ🏠(コンポーネント or
use〇〇)
7) ミニ練習🎮:2つのコンポーネントで同じロジックを共有しよ!
やること💪✨
useToggleを作る(ON/OFF)- 2つの別コンポーネントで使う
useToggle.ts
import { useState } from "react";
export function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = () => setOn((v) => !v);
const setTrue = () => setOn(true);
const setFalse = () => setOn(false);
return { on, toggle, setTrue, setFalse };
}
A.tsx
import { useToggle } from "./useToggle";
export function A() {
const { on, toggle } = useToggle(false);
return (
<section>
<h2>Aちゃん</h2>
<p>{on ? "ON 🌞" : "OFF 🌙"}</p>
<button onClick={toggle}>切り替え</button>
</section>
);
}
B.tsx
import { useToggle } from "./useToggle";
export function B() {
const { on, setTrue, setFalse } = useToggle(true);
return (
<section>
<h2>Bちゃん</h2>
<p>{on ? "ON 🔥" : "OFF 🧊"}</p>
<button onClick={setTrue}>ONにする</button>
<button onClick={setFalse}>OFFにする</button>
</section>
);
}
App.tsx
import { A } from "./A";
import { B } from "./B";
export function App() {
return (
<div>
<A />
<hr />
<B />
</div>
);
}
🎉 できたら大成功! 「同じロジックを2回書かずに済んだ」=カスタムフックの勝ち💖😆
まとめ🧁✨
- Reactは フックを呼んだ順番で状態を管理してるよ🧠
- だからフックは 順番が変わる場所(if/for/ネスト)で呼ぶと危険💥
- “フックを使う再利用ロジック”は カスタムフック(
use〇〇) にするのが安全&読みやすい🎀
次の章(第133章)で「名前は use で始める」ルールをもっと気持ちよく整理していこう〜!😊✨