当サイトは、アフィリエイト広告を利用しています

【ReactHooks】カスタムフックの使い方

作成日:2025月08月11日
更新日:2025年08月11日

Reactで開発する時によく使うカスタムフックについてまとめる。

当記事では

  • カスタムフックとは?
  • カスタムフックのルール
  • カスタムフック実装
  • カスタムフックの利点

について実装しながら解説する

カスタムフックとは?

カスタムフックとは、Reactの組み込みフック (useState, useEffect, など)を
使って自分で作る再利用可能な関数のこと。

つまり下記のようなイメージ

  • 組み込みフック + ロジックの組み合わせ = カスタムフック

カスタムフックのルール

Reactのフック(組み込みフックとカスタムフック)には大きく分けると

  1. フックのルール(Rules of Hooks)
  2. カスタムフック固有のルール
    • マスト(必須)
    • ベストプラクティス(推奨)

の2つのルールがある。

1. フックのルール(Rules of Hooks)

フックのルール(Rules of Hooks)は

  • フックは関数の「トップレベル」で呼ぶ
  • フックはReact関数コンポーネント or カスタムフックの中でのみ使う

でReactのすべてのフックに適用されるので
カスタムフックもReactの組み込みフック同様、このルールに従って作成、使用する必要がある。
いわば一番上のルール!
詳しくは下記記事参照

2. カスタムフック固有のルール

カスタムフックを作成する場合、フックのルール(Rules of Hooks)のルールを
守った上でさらに固有のルールがある。

そしてそのルールはマスト(必須)とベストプラクティス(推奨)に分類できる

マスト

マストなルールとしては

  1. 関数名をuseで始める
  2. 関数内でReactの組み込みフックを使う

がある。

これはReactの仕様やESLintのルールに関わるため絶対順守する

ベストプラクティス

ベストプラクティスは守らなくても動作はするが
コードの品質や保守性を高めるためには順守することが推奨されるルール

  1. UIロジック(alertなど)を含めない
  2. 戻り値をオブジェクトで返す
  3. 汎用性を意識して抽象化する

基本的に実装が難しいものではないので順守するようにしておく。

カスタムフックサンプル(ルール順守)

上記の1~5までのルールを順守したカスタムフックをサンプルとして作成してみる

カスタムフックサンプル(ルール順守)

useCounter.js
import { useState } from 'react';
export const useCounter = () => {
const [count, setCount] = useState(0);
const increment = () => setCount((c) => c + 1);
const decrement = () => setCount((c) => c - 1);
return { count, increment, decrement };
};

カスタムフックを使用するコンポーネント

App.js
import React from 'react';
import { useCounter } from './useCounter';
export default function App() {
const { count, increment, decrement } = useCounter();
return (
<div>
<p>{count}</p>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
);
}

実際の動作サンプル

カスタムフックサンプル

カスタムフックの利点

カスタムフックを作成し、使用するメリットについてもまとめておく。

メリットとしては下記が考えれれる。

  • 複数のフックをまとめられる
  • コンポーネントの簡潔化
  • ロジックの再利用

複数のフックをまとめられる

複数のReactの組み込みフックを使っている場合、それがどのロジックと
関係があるのがわかりにくいことがあるが、カスタムフックにすることで
フックとロジックを一箇所に集約できる

コンポーネントの簡潔化

たとえば

  • 状態管理(useState)
  • 操作関数(increment, decrement)

をカスタムフックに切り出すことで、コンポーネントはUIのみに集中できる。
この点からもUIロジックはカスタムフックに入れるべきではない。

こうすることでJSXがすっきりして読みやすくなる。

ロジックの再利用

複数のコンポーネントで同様の処理をする場合に
汎用的な処理をカスタムフックにすることで共通的に使用できる。

カスタムフックサンプル(メリット)

カスタムフックの利点を説明するサンプルを実装する

カスタムフックサンプル(メリット)

useCounter.js
import { useState, useEffect } from 'react';
export const useCounter = (initial = 0) => {
const [count, setCount] = useState(initial);
const increment = () => setCount((c) => c + 1);
const decrement = () => setCount((c) => c - 1);
useEffect(() => {
console.log(`Count changed: ${count}`);
}, [count]); // count が変わるたびにログを出す
return { count, increment, decrement };
};
  • useState, useEffectとそれを使用するロジックをまとめている

カスタムフックを使用するコンポーネント

App.js
import React from 'react';
import { useCounter } from './useCounter';
export default function App() {
const { count, increment, decrement } = useCounter();
return (
<div>
<p>{count}</p>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
);
}
  • 状態管理等のUI以外の部分はカスタムフックにしているのでコードが見やすい
  • useCounterは別のコンポーネントでも使用可能※汎用的

実行サンプル

メリットサンプル

カスタムフックに書くべきロジックの種類

Reactの組み合わせフック(useState, useEffect など)を使う処理は、
カスタムフックとして定義するのが適している
一方で、Reactのフックを使わない純粋な処理(例:日付フォーマット、文字列変換など)は、
通常の関数として定義すれば十分。

よくあるパターンとして

  • 状態管理系
  • 非同期通信系

の処理を行うカスタムフックが多い気がする ※状態管理系はサンプルで説明してるので割愛

非同期通信系

非同期通信を行うカスタムフックをサンプルとして実装してみる

非同期通信カスタムフック

useFetchData.js
import { useState, useEffect } from 'react';
export const useFetchData = (url) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
if (!url) {
return;
}
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Fetch failed: response not OK');
}
const json = await response.json();
setData(json);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
fetchData();
}, [url]);
return { data, isLoading, error };
};

カスタムフックを使用するコンポーネント

App.js
import React from 'react';
import { useFetchData } from './useFetchData';
export default function App() {
const { data, isLoading, error } = useFetchData(
'https://jsonplaceholder.typicode.com/users'
);
if (isLoading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
return (
<ul>
{data.map((user) => {
return <li key={user.id}>{user.name}</li>;
})}
</ul>
);
}

動作確認サンプル

fetch_customhook

まとめ

Reactのカスタムフックの作成方法と使い方についてまとめてみた。
カスタムフックはうまく使うと開発効率や保守性が格段に上がるので
もっと勉強していきたい。

新着記事

top