カテゴリ: React 更新日: 2026/01/31

Reactのカスタムフックでよくあるエラーと解決方法を初心者向けに解説

カスタムフックでよくあるエラーと解決方法
カスタムフックでよくあるエラーと解決方法

先生と生徒の会話形式で理解しよう

生徒

「先生、カスタムフックを作ったらエラーが出てしまいました。どうしたらいいですか?」

先生

「カスタムフックではよくあるエラーがいくつかあります。それぞれ原因と解決方法を順番に見ていきましょう。」

生徒

「エラーって怖いです…。初心者でもわかるように教えてください!」

先生

「もちろんです。まずはReactのルールを知ることが大切です。」

1. フックの呼び出しルール違反エラー

1. フックの呼び出しルール違反エラー
1. フックの呼び出しルール違反エラー

カスタムフックはReact関数コンポーネントまたは他のカスタムフックの中でしか呼び出せません。これを破ると「Hooks can only be called inside the body of a function component」というエラーが出ます。

例えば、普通の関数やイベントハンドラーの中で呼び出すとエラーになります。


function fetchData() {
  const [data, setData] = useCustomHook(); // ❌エラーになる
}

解決方法は、フックを関数コンポーネント内またはカスタムフック内に移動させることです。


function App() {
  const [data, setData] = useCustomHook(); // ✅正しい
}

2. 依存関係配列の指定ミスによる無限ループ

2. 依存関係配列の指定ミスによる無限ループ
2. 依存関係配列の指定ミスによる無限ループ

useEffectを使ったフックで依存関係配列を正しく指定しないと、レンダリングが無限に繰り返されることがあります。


useEffect(() => {
  fetchData();
}); // ❌依存配列が空でないので毎回実行される

解決方法は、依存関係配列を正しく設定することです。配列に必要な変数を入れるか、空配列で初回のみ実行にします。


useEffect(() => {
  fetchData();
}, []); // ✅初回だけ実行

3. 状態管理の初期化忘れ

3. 状態管理の初期化忘れ
3. 状態管理の初期化忘れ

useStateで初期値を設定しないと、undefinedを扱うエラーが出ることがあります。例えば、オブジェクトのプロパティにアクセスするとエラーになります。


const [user, setUser] = useState(); 
console.log(user.name); // ❌userがundefinedなのでエラー

解決方法は、初期値を空オブジェクトやnullで設定して、レンダリング時に安全に扱うことです。


const [user, setUser] = useState({ name: "" }); 
console.log(user.name); // ✅安全にアクセスできる

4. 非同期処理のタイミング問題

4. 非同期処理のタイミング問題
4. 非同期処理のタイミング問題

カスタムフック内で非同期処理を行う場合、コンポーネントがアンマウントされたあとに状態更新を行うとエラーが出ます。「Can't perform a React state update on an unmounted component」と表示されます。

解決方法は、フラグを使ってアンマウント後の更新を防ぐことです。


useEffect(() => {
  let isMounted = true;
  fetchData().then(result => {
    if (isMounted) setData(result);
  });
  return () => { isMounted = false; };
}, []);

5. フックのネーミングやファイル管理の注意

5. フックのネーミングやファイル管理の注意
5. フックのネーミングやファイル管理の注意

カスタムフックは必ずuseから始まる名前にする必要があります。例えば、useCounterやuseFetchなどです。これを守らないと、Reactがフックとして認識せず、意図しない動作になります。

また、フックごとにファイルを分け、再利用性を高めるとエラーの原因を特定しやすくなります。

6. まとめに変わる考え方

6. まとめに変わる考え方
6. まとめに変わる考え方

Reactのカスタムフックでよくあるエラーは、呼び出しルール、依存関係配列、状態初期化、非同期処理、ネーミングの順守などがポイントです。これらを意識すれば、エラーを防ぎ、効率的にフックを作成できます。

まとめ

まとめ
まとめ

Reactのカスタムフック開発において、エラーに直面することは決して珍しいことではありません。むしろ、エラーは自分のコードをより堅牢にするための貴重なフィードバックです。今回ご紹介した「フックの呼び出しルール」「依存関係の管理」「初期値の設定」「非同期処理のクリーンアップ」「命名規則」という5つのポイントは、Reactエンジニアが日常的に意識すべき極めて重要な要素です。

特にカスタムフックは、ロジックを共通化してアプリケーション全体の可読性を高めるための強力なツールです。しかし、その強力さゆえに、一箇所でのミスが複数のコンポーネントに影響を及ぼす可能性もあります。まずは基礎的なルールを徹底し、小さなフックから作り始めて徐々に複雑なロジックへとステップアップしていくのが、上達への近道と言えるでしょう。

実践的なカスタムフックの例:useCounter

ここで、これまでの教訓を活かしたシンプルなカスタムフックの例を振り返ってみましょう。状態管理の初期化や、名前の付け方、関数コンポーネントでの呼び出し方を再確認してください。


import { useState, useCallback } from "react";

/**
 * 数値をカウントアップ・ダウンするカスタムフック
 * 初期値を引数として受け取り、安全に状態を管理します
 */
export const useCounter = (initialValue = 0) => {
  const [count, setCount] = useState(initialValue);

  // 関数の再生成を抑えるためにuseCallbackを使用
  const increment = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);

  const decrement = useCallback(() => {
    setCount((prev) => prev - 1);
  }, []);

  const reset = useCallback(() => {
    setCount(initialValue);
  }, [initialValue]);

  return { count, increment, decrement, reset };
};

このカスタムフックをコンポーネントで利用する

作成したカスタムフックを実際の画面で使ってみます。Reactのルール通り、関数コンポーネントのトップレベルで呼び出している点に注目してください。


import React from "react";
import { useCounter } from "./useCounter";

function CounterDisplay() {
  // カスタムフックを呼び出す(useから始まる命名を守っています)
  const { count, increment, decrement, reset } = useCounter(10);

  return (
    <div className="container mt-4">
      <h3>現在のカウント: {count}</h3>
      <div className="btn-group">
        <button className="btn btn-primary" onClick={increment}>増加</button>
        <button className="btn btn-danger" onClick={decrement}>減少</button>
        <button className="btn btn-secondary" onClick={reset}>リセット</button>
      </div>
    </div>
  );
}

export default CounterDisplay;
(画面に「現在のカウント: 10」と表示され、増加ボタンを押すと数字が増え、減少ボタンで減り、リセットで10に戻ります)

このように、ロジックをカスタムフック(useCounter)に切り出すことで、UIを担当するコンポーネント(CounterDisplay)が非常にスッキリします。エラーを恐れず、どんどん「自分だけの便利なフック」を作ってみてください。デバッグの際は、ブラウザのコンソールに出るエラーメッセージをよく読み、それが「ルールの違反」なのか「ロジックのミス」なのかを冷静に判断することが解決への近道です。

最後に、Reactの公式ドキュメントや最新のベストプラクティスを定期的にチェックすることも忘れずに。技術の進化は早いですが、今回学んだような「Hooksの基本原則」は、長く使える一生モノのスキルになります。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!カスタムフックのエラーって、実は自分がReactの基本的なルールをうっかり忘れている時に起きることが多いんですね。」

先生

「その通りです。特に『フックはループや条件分岐の中で呼んではいけない』というルールや、依存関係配列の指定ミスは、ベテランでも時々やってしまうミスなんですよ。エラーが出た時は『Reactが正しく動こうとして教えてくれているんだ』とポジティブに捉えましょう。」

生徒

「なるほど。さっきのuseCounterの例を見て思ったのですが、useCallbackを使っているのは、パフォーマンスを意識してのことですか?」

先生

「鋭いですね!カスタムフックから関数を返す場合、その関数が他のuseEffectの依存関係に含まれることもあるので、メモ化しておくのが安全なんです。これをしないと、意図しない再レンダリングや無限ループの原因になることもありますからね。」

生徒

「深いですね……。でも、まずは『use』から名前を始めて、コンポーネントの先頭で呼ぶ、という基本から徹底してみます!非同期処理のクリーンアップも、useEffectの戻り値で関数を返す(isMountedを使う)方法がわかったので、もう怖くありません。」

先生

「素晴らしい意気込みです。もし実行結果が思うようにいかない時は、さっきのalertで解説したような動作イメージを頭の中でシミュレーションしてみてください。Reactのステート更新がどのタイミングで起きているかを理解すれば、デバッグ能力は飛躍的に向上しますよ。」

生徒

「はい!自分でも色々な機能を持ったカスタムフックを作って、共通化のメリットを実感してみます。また分からないことがあったら教えてください!」

先生

「もちろんです。試行錯誤を繰り返すことで、コードはどんどん綺麗になっていきます。頑張りましょうね!」

カテゴリの一覧へ
新着記事
New1
React
Reactコンポーネントの再利用と分割を完全マスター!初心者でもわかるコンポーネント設計
New2
React
ReactでAxiosインターセプターの使い方を完全ガイド!初心者でもわかるリクエストとレスポンスの処理方法
New3
React
JSXの書き方!初心者でもわかるReactタグと属性の基本ルール解説
New4
React
ReactとDockerを使った開発環境構築の基本を徹底解説!初心者でもわかるReactとDockerの連携方法
人気記事
No.1
Java&Spring記事人気No1
React
ReactでonChangeイベントを使ってフォーム入力値を管理する方法を初心者向けに解説
No.2
Java&Spring記事人気No2
React
Reactのイベントハンドリングのアンチパターンまとめ!初心者でもわかる注意点
No.3
Java&Spring記事人気No3
React
ReactとTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.4
Java&Spring記事人気No4
React
ReactでFetch APIのローディング状態を管理する方法|初心者にもわかる解説
No.5
Java&Spring記事人気No5
React
Reactのカスタムフックの作り方を完全ガイド!再利用可能なロジックを切り出す仕組み
No.6
Java&Spring記事人気No6
React
create-react-appでReactプロジェクトを作成する手順を初心者向けに完全解説!
No.7
Java&Spring記事人気No7
React
ReactのuseStateとuseEffectでよくあるエラーと解決方法ガイド!初心者でもわかるReactフック
No.8
Java&Spring記事人気No8
React
Reactでファイルアップロードを実装する方法を解説!Fetch APIで画像やPDFを送る仕組みを初心者向けに紹介