React で「Invalid hook call」が解決できない
Hook をコンポーネント関数のトップレベル以外で呼んだ、または react が二重に読み込まれていると Invalid hook call が出る。
呼び出し位置と react / react-dom のバージョン整合を確認する。
#react#hooks#rules-of-hooks#invalid-hook-call
要約
Invalid hook call. Hooks can only be called inside of the body of a function component は、Hook の呼び出し位置が不正 か react が二重に読み込まれている ときに出る。useState などはコンポーネント関数か use で始まるカスタム Hook の トップレベル でしか呼べない。
位置とバージョン整合の 2 点を順に潰す。
よくある原因
- トップレベル以外で呼んでいる: 条件分岐・ループ・
try、イベントハンドラやネストした関数の中でuseStateなどを呼んでいる - 対象外の関数から呼んでいる: 通常のユーティリティ関数やクラスコンポーネントから Hook を呼んでいる
- バージョン不一致:
reactとreact-domのメジャーが揃っていない - react の重複: モノレポや
npm linkでreactが 2 つ入り、Hook のディスパッチャが分裂している
解決策
1. トップレベルで呼ぶ
// NG: 条件の内側で呼んでいる
function Comp({ on }: { on: boolean }) {
if (on) {
const [v, setV] = useState(0);
}
return null;
}
// OK: 先に Hook、分岐はその後
function Comp({ on }: { on: boolean }) {
const [v, setV] = useState(0);
return on ? <span>{v}</span> : null;
}呼び出し順を毎回同じにするのが Rules of Hooks の原則。
2. 呼べる場所か確認する
Hook を使ってよいのは関数コンポーネント本体か、名前が use で始まるカスタム Hook の中だけ。
それ以外の関数からロジックを切り出すときは、カスタム Hook 化する。
3. バージョンを揃える
npm ls react react-domreact と react-dom を同一メジャーに合わせる。
片方だけ更新した状態が典型的な不一致。
4. react の重複を解消する
npm dedupe
npm ls react # 1 つだけになっているか確認それでも 2 つ残るなら、bundler 側で react を単一パスに alias する。
重複時の詳しい対処は Invalid hook call 警告の公式解説 に整理されている。