Skip to content

Instantly share code, notes, and snippets.

@yukikim
Created November 14, 2024 07:46
Show Gist options
  • Save yukikim/fe0833a3276759446a31f01bff795ed6 to your computer and use it in GitHub Desktop.
Save yukikim/fe0833a3276759446a31f01bff795ed6 to your computer and use it in GitHub Desktop.
React非同期コンポーネント

TypeScript と React を使って非同期 (async) コンポーネントを作成する方法について説明します。非同期処理が必要な場合、通常は API リクエストやデータフェッチを行うことが多いです。このため、非同期コンポーネントを作成するには、React の useEffectuseState フックを利用して、非同期処理をコンポーネント内で管理することが一般的です。

以下に、非同期コンポーネントの作成手順を示します。

1. 基本的な非同期コンポーネント

非同期データを取得する最も一般的な方法は、useEffect フックを使用してデータを取得し、useState フックでそのデータを保持することです。

import React, { useEffect, useState } from 'react';

type Data = {
  id: number;
  title: string;
  body: string;
};

const AsyncComponent: React.FC = () => {
  const [data, setData] = useState<Data | null>(null); // データの状態
  const [loading, setLoading] = useState<boolean>(true); // ローディング状態
  const [error, setError] = useState<string | null>(null); // エラーメッセージ

  // 非同期データの取得
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!response.ok) {
          throw new Error('データの取得に失敗しました');
        }
        const result: Data = await response.json();
        setData(result);
      } catch (err) {
        setError('データの取得に失敗しました');
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // コンポーネントがマウントされたときに1回だけ実行

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>{error}</div>;
  }

  if (!data) {
    return <div>No data found</div>;
  }

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  );
};

export default AsyncComponent;

解説:

  1. useState: 非同期処理で取得するデータ、ローディング状態、エラーメッセージを管理します。
  2. useEffect: コンポーネントがマウントされたときに一度だけ非同期処理を実行するために使用します。
  3. fetch: データを取得するための非同期リクエストを行います。asyncawait を使って非同期処理を簡潔に書きます。

2. エラーハンドリングとローディング表示

上記の例では、データが読み込まれている間にローディングメッセージを表示し、エラーが発生した場合にはエラーメッセージを表示します。このように、非同期データの取得には通常、ローディング状態エラーハンドリング が伴います。

3. 非同期コンポーネントをさらにカスタマイズする

非同期処理をもっと柔軟にしたい場合、例えば、再フェッチやリトライ機能を追加したい場合などには、以下のようにカスタマイズできます。

3.1 再フェッチ機能の追加

例えば、ボタンを押すと再度データをフェッチするようにすることができます。

import React, { useEffect, useState } from 'react';

type Data = {
  id: number;
  title: string;
  body: string;
};

const AsyncComponent: React.FC = () => {
  const [data, setData] = useState<Data | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  const fetchData = async () => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
      if (!response.ok) {
        throw new Error('データの取得に失敗しました');
      }
      const result: Data = await response.json();
      setData(result);
    } catch (err) {
      setError('データの取得に失敗しました');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData();
  }, []); // コンポーネントマウント時に初回のデータ取得

  return (
    <div>
      {loading && <div>Loading...</div>}
      {error && <div>{error}</div>}
      {data && (
        <div>
          <h1>{data.title}</h1>
          <p>{data.body}</p>
          <button onClick={fetchData}>再フェッチ</button>
        </div>
      )}
    </div>
  );
};

export default AsyncComponent;

このコードでは、再フェッチボタン を追加し、ユーザーがボタンを押すと非同期リクエストが再実行されます。

4. 非同期データを使った TypeScript 型の管理

非同期で取得するデータが型安全であることを確認するために、TypeScript の型を使って、API レスポンスに合わせた型を定義しておくことが重要です。上記の例では、Data 型を定義して、それに合わせて useState フックや API のレスポンスを型付けしています。

5. Suspense と Lazy Loading を使う

React には Suspenselazy を使ってコンポーネントの遅延読み込みを行う機能もありますが、これは主にコンポーネントを遅延ロードするためのもので、非同期データフェッチには直接関係しません。しかし、非同期処理をコンポーネントの遅延ロードと組み合わせて使うこともできます。

以下の例では、React の Suspenselazy を使って、非同期コンポーネントを遅延読み込みします。

import React, { Suspense, lazy } from 'react';

// 非同期でコンポーネントを読み込む
const AsyncComponent = lazy(() => import('./AsyncComponent'));

const App: React.FC = () => {
  return (
    <div>
      <h1>非同期コンポーネントの例</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <AsyncComponent />
      </Suspense>
    </div>
  );
};

export default App;

このコードでは、AsyncComponent を遅延読み込みしており、読み込む間に Suspense によってローディング状態が表示されます。

結論

TypeScript と React で非同期コンポーネントを作成するには、useEffectuseState を活用して非同期処理を管理し、ローディング状態やエラーハンドリングを追加するのが一般的です。また、Suspenselazy を使ってコンポーネントの遅延読み込みもできますが、非同期データの取得自体は useEffect 内で行うのが通常の方法です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment