【Next.jsエラー対策】Rendered fewer hooks than expected の原因と対処法【useState/useEffect】

はじめに

こんにちは、Procom開発者です!

今回は、Next.js のクライアントコンポーネント('use client')で以下のような致命的なエラーに遭遇しました。

Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

一見、何が起こっているのか分かりづらいこのエラー。実は、Reactフックのルールに違反したことが原因でした。


結論:useStateuseEffect の「前に return しちゃダメ!」


エラー全文と発生箇所

Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

発生したのは、SNS埋め込み用の以下のようなコンポーネントでした:

export default function FacebookEmbedBlock({ uid, isEditable }: Props) {
const [fbUrl, setFbUrl] = useState('');
const [showFacebook, setShowFacebook] = useState<boolean | undefined>(undefined);

// ❌ useState の後に return するべき → これがダメな例
if (!isEditable && (!fbUrl || showFacebook === false)) {
return null;
}

// useEffect など...
}

原因:React のフックは「条件分岐の前」に書かなければならない

Reactでは以下のルールがあります。

✅ すべての useState, useEffect などのフックは「無条件に」常に同じ順序で呼び出されなければならない。

つまり、

if (...) {
return null; // ← useState の前に return しちゃうと…
}
const [x, setX] = useState(); // ← これがスキップされて "fewer hooks" エラーになる

このように、一部の条件で useState の実行自体をスキップしてしまうと、Reactの内部のフックの順序が狂ってしまいクラッシュします。


対策:すべての useStateuseEffectreturnより上に書く

修正後のコード例:

export default function FacebookEmbedBlock({ uid, isEditable }: Props) {
const [fbUrl, setFbUrl] = useState('');
const [showFacebook, setShowFacebook] = useState<boolean | undefined>(undefined);

// ✅ 必ずフックの「あと」で return する
if (!isEditable && (!fbUrl || showFacebook === false)) {
return null;
}

useEffect(() => {
// ...
}, []);
}

これで Rendered fewer hooks than expected エラーは解消されます。


応用:フックの後に「早期 return」を使うことは可能

Reactでは以下のように**「フックのあと」で return するのはOK**です:

function MyComponent() {
const [loaded, setLoaded] = useState(false);

if (!loaded) return null; // ✅ これはOK(useState後)

return <div>表示OK</div>;
}

Procomでの実例(TikTok, Facebook, Instagram)

Procomの開発では、SNS埋め込みごとに表示フラグ(showFacebook, showInstagram, showTikTok など)を導入し、次のように修正しました:

if (!isEditable && (!fbUrl || showFacebook === false)) {
return null; // ✅ useStateなど全てのhookの後に記述
}

この修正によって、他ユーザーが非表示設定をしたSNSは安全に表示されず、かつフックエラーも回避できました。


おわりに:フックの順序は「聖域」

今回のエラーはReactにおける基本ルール違反でしたが、Next.jsのような構成では早期returnが複雑になりがちです。

✅ 覚えておきたいポイント:

  • useState, useEffect必ず関数の最上部で定義
  • 条件による return はそのあと
  • optional chaining(?.)と ?? などで安全にフラグ管理

あなたのReactアプリでも同じ症状が出たら…

このエラーが出たら、一番上のreturn文を疑いましょう!


もしこの記事が役立ったら、ぜひ Procom もチェックしてみてください!
あなたのすべてを、ここに集約。Procomでプロフィールをまとめよう。

おすすめの記事