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

Reactのカスタムフックの実践例まとめ!便利スニペット集で学ぶ

カスタムフックの実践例まとめ(便利スニペット集)
カスタムフックの実践例まとめ(便利スニペット集)

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

生徒

「先生、カスタムフックって便利そうだけど、どんな例がありますか?」

先生

「いくつかの実践的なスニペットを使うと、すぐに役立つフックを作れますよ。」

生徒

「具体的にどんなスニペットですか?」

先生

「それでは、簡単な例を順番に紹介します!」

1. ローカルストレージと同期するカスタムフック

1. ローカルストレージと同期するカスタムフック
1. ローカルストレージと同期するカスタムフック

useStateとuseEffectを組み合わせて、データをブラウザのローカルストレージに保存するフックです。ページをリロードしても値が保持されます。


import { useState, useEffect } from "react";

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}

export default useLocalStorage;
(値を更新すると自動でローカルストレージに保存され、ページをリロードしても値が保持されます)

2. ウィンドウサイズを取得するフック

2. ウィンドウサイズを取得するフック
2. ウィンドウサイズを取得するフック

ブラウザの幅や高さをリアルタイムで取得できるカスタムフックです。レスポンシブ対応に便利です。


import { useState, useEffect } from "react";

function useWindowSize() {
  const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

  useEffect(() => {
    const handleResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return size;
}

export default useWindowSize;
(ブラウザのサイズが変わると自動で値が更新されます)

3. フォーム入力をまとめて管理するフック

3. フォーム入力をまとめて管理するフック
3. フォーム入力をまとめて管理するフック

フォームの入力値をオブジェクトでまとめて管理できます。inputやtextareaのonChangeハンドラーに便利です。


import { useState } from "react";

function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues(prev => ({ ...prev, [name]: value }));
  };

  return [values, handleChange];
}

export default useForm;
(複数のフォーム入力をまとめて管理でき、更新も簡単に行えます)

4. APIデータを取得するフック

4. APIデータを取得するフック
4. APIデータを取得するフック

非同期でAPIからデータを取得するカスタムフックです。読み込み中やエラーも状態で管理できます。


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [url]);

  return { data, loading, error };
}

export default useFetch;
(APIデータを取得して状態に反映し、ロード中やエラーも扱えます)

5. 前回の値を保持するフック

5. 前回の値を保持するフック
5. 前回の値を保持するフック

前回の値を保持して比較したいときに便利なカスタムフックです。値の変化を監視する際に役立ちます。


import { useRef, useEffect } from "react";

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

export default usePrevious;
(前回の値を保持して、状態変化の比較などに使えます)

6. カスタムフックで作業効率をアップ

6. カスタムフックで作業効率をアップ
6. カスタムフックで作業効率をアップ

今回紹介したスニペットを使うと、状態管理、フォーム操作、API通信、ウィンドウ操作などの共通処理を簡単に再利用できます。自分用の便利フック集を作ることで、React開発の効率が大幅にアップします。

まとめ

まとめ
まとめ

React開発において、カスタムフックを活用することは、単にコードを短くする以上の大きなメリットをもたらします。今回ご紹介した「ローカルストレージの同期」「ウィンドウサイズの監視」「フォーム管理」「API通信」「前回の値の保持」といったスニペットは、実務の現場でも頻繁に登場するロジックばかりです。これらを共通部品として切り出すことで、コンポーネント本体は「見た目(UI)」の構築に専念でき、プログラム全体の可読性とメンテナンス性が劇的に向上します。

カスタムフックを作成する際のポイントは、再利用性を意識しつつも、特定のビジネスロジックに依存しすぎない「汎用的なインターフェース」を設計することです。例えば、今回紹介した useFetch フックをさらに拡張して、認証トークンを自動で付与する機能や、リトライ処理を追加することも可能です。自分自身のプロジェクトに合わせたオリジナルのフック集を育てていくことは、開発者としての大きな資産になるでしょう。

応用編:複数のカスタムフックを組み合わせる実践テクニック

実際のアプリケーション開発では、一つのコンポーネント内で複数のカスタムフックを組み合わせて使用することが一般的です。例えば、ショッピングサイトの「ユーザー設定画面」を想定してみましょう。

以下のサンプルコードは、今回学んだ useFormuseLocalStorage を組み合わせて、フォームの入力内容をリアルタイムでブラウザに保存する高度な実装例です。これにより、ユーザーが誤ってページを閉じてしまっても、入力内容が消えない親切なUIを実現できます。


import React, { useEffect } from "react";
import useForm from "./hooks/useForm";
import useLocalStorage from "./hooks/useLocalStorage";

function UserProfileEditor() {
  // ローカルストレージから初期データを取得
  const [savedProfile, setSavedProfile] = useLocalStorage("user_profile", {
    userName: "",
    bio: ""
  });

  // フォームの状態管理にカスタムフックを利用
  const [values, handleChange] = useForm(savedProfile);

  // 入力値が変わるたびにストレージに保存する(自動保存機能)
  useEffect(() => {
    setSavedProfile(values);
  }, [values, setSavedProfile]);

  return (
    <div className="p-4 border rounded shadow-sm">
      <h3 className="mb-3">プロフィール編集</h3>
      <div className="mb-3">
        <label className="form-label">ユーザー名</label>
        <input
          type="text"
          name="userName"
          className="form-control"
          value={values.userName}
          onChange={handleChange}
        />
      </div>
      <div className="mb-3">
        <label className="form-label">自己紹介</label>
        <textarea
          name="bio"
          className="form-control"
          value={values.bio}
          onChange={handleChange}
        />
      </div>
      <div className="text-muted small">
        ※入力内容は自動的にブラウザへ保存されます。
      </div>
    </div>
  );
}

export default UserProfileEditor;
(ユーザーが名前や自己紹介を入力するたびにローカルストレージが更新され、次回アクセス時にも内容が復元されます)

最新のReact開発におけるカスタムフックの重要性

Next.js(App Router)の普及により、サーバーコンポーネントとクライアントコンポーネントの使い分けが重要視されるようになりました。カスタムフックは「クライアントサイドのロジック」をカプセル化するための強力な武器となります。ブラウザ特有のAPI(windowオブジェクトやlocalStorageなど)にアクセスする処理は、すべてカスタムフックの中に閉じ込めておくことで、コンポーネントの構造がすっきりとし、デバッグも格段に楽になります。

また、TypeScriptを導入しているプロジェクトであれば、カスタムフックの引数や戻り値に適切な型(InterfaceやType)を定義することで、型安全な開発が可能になります。例えば、useFetch<T> のようにジェネリクスを活用すれば、取得するデータの型を呼び出し側で指定でき、予測可能なプログラミングが実現できます。

これからReactをより深く学びたい方は、ライブラリが提供している標準フック(useState, useEffect, useContext, useMemo, useCallback)の挙動を正しく理解した上で、それらを組み合わせて「自分だけの便利な道具箱」を作ってみてください。コードの重複を減らし、宣言的な記述を心がけることで、プロフェッショナルなフロントエンドエンジニアへの道が開けるはずです。

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

生徒

「先生、まとめの記事を読んでカスタムフックの凄さがさらによく分かりました!特に複数のフックを組み合わせる方法は、実際のアプリ開発ですぐに使えそうですね。」

先生

「その通りです。一つひとつのフックはシンプルですが、それらをレゴブロックのように組み合わせることで、複雑な機能も驚くほど綺麗に実装できるのがReactの醍醐味なんですよ。」

生徒

「今まではコンポーネントの中にuseEffectやuseStateをたくさん書いてしまって、コードが長くなって困っていたんです。これからはカスタムフックに切り出して、再利用性を高めるように意識してみます。」

先生

「素晴らしい意気込みですね!特に useForm のようなフックは、一度作っておけばどんなプロジェクトでも使い回せます。最初は既存のスニペットを模倣するところから始めて、徐々に自分なりのアレンジを加えていくのが上達の近道ですよ。」

生徒

「TypeScriptでの型定義についても触れられていましたが、ジェネリクスを使うとさらに便利になりそうですね。次は、API通信のフックを型安全に実装することに挑戦してみたいと思います!」

先生

「いいですね。型安全なカスタムフックはチーム開発でも非常に喜ばれます。エラーの少ない、堅牢なアプリケーションを目指して頑張りましょう。もし実装で迷ったら、いつでも相談してくださいね。」

生徒

「はい!ありがとうございます。カスタムフックを活用して、もっとスマートなコードが書けるように練習を積み重ねます!」

カテゴリの一覧へ
新着記事
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とTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.3
Java&Spring記事人気No3
React
Reactのイベントハンドリングのアンチパターンまとめ!初心者でもわかる注意点
No.4
Java&Spring記事人気No4
React
Reactのカスタムフックの作り方を完全ガイド!再利用可能なロジックを切り出す仕組み
No.5
Java&Spring記事人気No5
React
ReactでFetch APIのローディング状態を管理する方法|初心者にもわかる解説
No.6
Java&Spring記事人気No6
React
ReactのuseStateとuseEffectでよくあるエラーと解決方法ガイド!初心者でもわかるReactフック
No.7
Java&Spring記事人気No7
React
create-react-appでReactプロジェクトを作成する手順を初心者向けに完全解説!
No.8
Java&Spring記事人気No8
React
Reactのフォーム処理でよくあるエラーと解決法を完全解説!初心者でも安心して学べるReact入門