0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[React][Hooks] Custom Hooks `useFetch` の使い方

Last updated at Posted at 2025-08-02

概要

  • Reactコンポーネントで外部APIを呼び出す方法として、再利用可能なuseFetchカスタムフックを活用する方法を紹介
  • 最小構成から、実誤的なAPI活用例「JSONPlaceholder / GitHub API / CoinMarketCap API」までを解説
  • TypeScriptによる汎用的な型定義で、型安全かつ保守性の高い構成を実現

実施条件

  • React + TypeScript プロジェクトが構築済みであること
  • 外部APIにアクセスできるネットワーク環境があること
  • npm/yarn で依存関係を追加できる環境であること
  • CoinMarketCapのAPIキー〈無料で取得可能〉を所持していること

環境

ツール バージョン 目的
Node.js 22.5.1 Reactアプリ実行環境
React 19.1.0 UIコンポーネントの構築
TypeScript 4.9 型定義による安全な開発
fetch API ブラウザ標準搭載 API通信処理

型定義セクション

// 型定義セクション
export type MessageResponse = {
  message: string;
};

export type Post = {
  userId: number;
  id: number;
  title: string;
  body: string;
};

export type GitHubUser = {
  login: string;
  avatar_url: string;
  html_url: string;
};

export type CoinMarketData = {
  data: {
    [symbol: string]: {
      name: string;
      quote: {
        USD: {
          price: number;
        };
      };
    };
  };
};

カスタムフックにおける基本構造

  1. importセクション
  2. 型定義セクション
  3. カスタムフック定義セクション
    1. 内部状態管理セクション
    2. 副作用(useEffect)処理セクション
    3. 返り値構築・ロジックセクション

基本構文: useFetch.ts

// importセクション
import { useEffect, useState } from 'react';

// カスタムフック定義セクション
export const useFetch = <T>(url: string, options?: RequestInit) => {
  // 内部状態管理セクション
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState<boolean>(true);

  // 副作用(useEffect)処理セクション
  useEffect(() => {
    fetch(url, options)
      .then((res) => {
        if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
        return res.json();
      })
      .then((json: T) => setData(json))
      .catch((err: Error) => setError(err.message))
      .finally(() => setLoading(false));
  }, [url, JSON.stringify(options)]); 

  // 返り値構築・ロジックセクション
  return { data, error, loading };
}

活用例

1. 投稿のタイトルを取得する(JSONPlaceholder)

// importセクション
import React from 'react';
import { useFetch } from './useFetch';

// 型定義セクション
import type { Post } from './types';

// 関数定義セクション
const FetchPostTitleWithHook: React.FC = () => {
  // 内部状態管理セクション(useFetchの呼び出し)
  const { data, error, loading } = useFetch<Post>('https://jsonplaceholder.typicode.com/posts/1');

  // イベントハンドラーセクション(特になし)

  // JSX構築セクション
  if (loading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error}</p>;
  if (!data) return <p>データなし</p>;

  return <h1>{data.title}</h1>;
};

export default FetchPostTitleWithHook;

2. GitHubユーザーのプロフィールを表示する

// importセクション
import React from 'react';
import { useFetch } from './useFetch';

// 型定義セクション
import type { GitHubUser } from './types';

// 関数定義セクション
const GitHubProfileWithHook: React.FC = () => {
  // 内部状態管理セクション(useFetchの呼び出し)
  const { data: user, error, loading } = useFetch<GitHubUser>('https://api.github.com/users/octocat');

  // イベントハンドラーセクション(特になし)

  // JSX構築セクション
  if (loading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error}</p>;
  if (!user) return <p>データなし</p>;

  return (
    <div>
      <h2>{user.login}</h2>
      <img src={user.avatar_url} alt="avatar" width={100} />
      <a href={user.html_url} target="_blank" rel="noopener noreferrer">GitHubを見る</a>
    </div>
  );
};

export default GitHubProfileWithHook;

3. CoinMarketCap APIでビットコインの価格を取得する

// importセクション
import React from 'react';
import { useFetch } from './useFetch';

// 型定義セクション
import type { CoinMarketData } from './types';

// 関数定義セクション
const CoinPriceWithHook: React.FC = () => {
  // 内部状態管理セクション(useFetchの呼び出し)
  const { data, error, loading } = useFetch<CoinMarketData>(
    'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=BTC'
  );

  // イベントハンドラーセクション(特になし)

  // JSX構築セクション
  if (loading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error}</p>;
  if (!data?.data?.BTC) return <p>データなし</p>;

  const price = data.data.BTC.quote.USD.price;
  return <h2>Bitcoin価格: ${price.toFixed(2)}</h2>;
};

export default CoinPriceWithHook;

fetchプロセスの流れ

  1. useEffectにより初回レンダリング時にAPI呼び出し
  2. fetchでHTTPリクエストを送信
  3. .json()でJSON解析
  4. setStateで状態更新し、UI再描画

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?