ReactのuseEffectで外部APIをポーリングする方法を徹底解説

Reactアプリケーションでは、リアルタイムデータの更新が求められる場面が少なくありません。例えば、チャットアプリのメッセージ取得、ライブ更新されるダッシュボード、またはユーザーの進捗データの定期確認などです。このようなシナリオでは、外部APIに定期的にリクエストを送り、最新データを取得する「ポーリング」という手法が役立ちます。本記事では、ReactのuseEffectフックを活用してAPIポーリングを実装する方法を、具体的なコード例を交えながらわかりやすく解説していきます。ポーリングの基本概念から、効率的な実装のベストプラクティスまで詳しく見ていきましょう。

目次

ReactのuseEffectの基本概要


ReactのuseEffectフックは、コンポーネントのライフサイクルに基づいて副作用(サイドエフェクト)を管理するための機能を提供します。副作用とは、データのフェッチ、DOMの操作、または外部APIとの通信のように、コンポーネントのレンダリング以外で実行される処理を指します。

useEffectの基本的な構文


useEffectは以下のような構文で使用します:

import React, { useEffect } from 'react';

function ExampleComponent() {
    useEffect(() => {
        // 副作用の処理
        console.log("Component rendered");

        // クリーンアップ処理
        return () => {
            console.log("Component unmounted");
        };
    }, []); // 依存配列

    return <div>Hello, World!</div>;
}

引数の説明

  1. 第1引数: 副作用の処理を定義する関数。
  2. 第2引数(依存配列): 副作用の再実行条件を指定。空の配列([])は初回レンダリング時のみ実行を意味します。

主な用途

  • データのフェッチ: APIからデータを取得し、コンポーネントに表示する。
  • イベントリスナーの設定: ウィンドウサイズの変更などのイベントを監視。
  • クリーンアップ: タイマーの解除やリスナーの削除など、リソースの解放を実行。

注意点

  • 無限ループの回避: 依存配列を適切に設定しないと、useEffectが無限に再実行される場合があります。
  • クリーンアップ処理: コンポーネントのアンマウント時に適切なリソース解放を行わないと、メモリリークが発生する可能性があります。

useEffectは、Reactの状態やコンポーネントのライフサイクルを効率的に管理するための基本的なツールであり、ポーリングの実装においても重要な役割を果たします。

ポーリングの仕組みとは

ポーリングの基本概念


ポーリングとは、一定間隔でサーバーやAPIにリクエストを送り、最新データを取得する手法です。この仕組みは、リアルタイム通信が必要なアプリケーションでよく用いられます。例えば、SNSの通知取得や、ライブデータを表示するダッシュボードなどがその代表例です。

ポーリングの利点

  • リアルタイム性の確保: 定期的にデータを更新することで、ユーザーに最新情報を提供します。
  • シンプルな実装: サーバー側の複雑な設定が不要で、クライアント側のコードで管理可能です。

ポーリングの課題

  • サーバー負荷の増加: 頻繁なリクエストはサーバーのリソースを圧迫する可能性があります。
  • ネットワークの非効率性: 必要でない場合でもリクエストが発生するため、帯域を浪費する可能性があります。

ポーリングが必要になるシーン


以下のようなケースでポーリングが有効です:

  • リアルタイム更新が必要: チャットアプリやオンラインゲームの状態更新。
  • 状態変化の監視: バッチ処理の進捗確認や、システムの稼働状況監視。
  • サーバーの非プッシュ対応: WebSocketやServer-Sent Eventsを利用できない場合の代替手段。

代替手法


ポーリングの課題を補うため、次のような技術が考慮される場合もあります:

  • WebSocket: 双方向通信が可能なプロトコルで、サーバー側のイベントを即時に受信可能。
  • Server-Sent Events(SSE): サーバーからクライアントへの一方向のリアルタイムデータ送信。

ポーリングは、アプリケーションの設計と要件に応じて選択すべき手法であり、その効率的な実装方法を知ることが重要です。

useEffectを使った基本的なポーリング実装

ポーリングの基本手順


ReactのuseEffectフックを活用すれば、簡単にポーリングを実現できます。以下に、基本的なポーリングのコード例を示します。

実装例

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

function PollingExample() {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);

    useEffect(() => {
        let isCancelled = false; // コンポーネントがアンマウントされた場合にポーリングを停止するためのフラグ

        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }
                const result = await response.json();
                if (!isCancelled) {
                    setData(result);
                }
            } catch (err) {
                if (!isCancelled) {
                    setError(err.message);
                }
            }
        };

        const intervalId = setInterval(fetchData, 5000); // 5秒ごとにAPIを呼び出し

        // クリーンアップ処理
        return () => {
            clearInterval(intervalId); // タイマーをクリア
            isCancelled = true; // リクエストを無効化
        };
    }, []); // 初回レンダリング時のみ実行

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

    return (
        <div>
            <h1>Polling Data</h1>
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
        </div>
    );
}

export default PollingExample;

コード解説

1. **状態管理**


useStateを使用して、取得したデータ(data)とエラーメッセージ(error)を管理します。

2. **データの取得**


fetchData関数でAPIにリクエストを送り、成功時にデータをdataに保存し、失敗時にerrorを更新します。

3. **定期実行**


setIntervalを利用して5秒ごとにfetchDataを呼び出します。ポーリングの間隔は、アプリケーション要件やサーバー負荷を考慮して適切に設定します。

4. **クリーンアップ**


clearIntervalを使い、コンポーネントのアンマウント時にタイマーを停止します。これにより、不要なリソース消費を防ぎます。

ポイント

  • ポーリング間隔の設定: ユーザー体験とサーバー負荷のバランスを取ることが重要です。
  • エラーハンドリング: ネットワークやAPIのエラーに対処するコードを含めることで、信頼性の高い実装が可能になります。

このコードをベースに、さらに最適化やカスタマイズを加えることで、より実用的なポーリング機能を構築できます。

適切な間隔の設定とその注意点

ポーリング間隔の重要性


ポーリングの間隔を適切に設定することは、ユーザー体験とサーバーリソースの効率的な利用に直結します。間隔が短すぎるとサーバー負荷やネットワークの無駄遣いが発生し、長すぎるとデータの更新頻度が低下してリアルタイム性が損なわれます。

間隔設定の考慮ポイント

  1. データの重要性: データのリアルタイム性が高く求められる場合は短い間隔(数秒)を検討。
  2. ユーザーのアクション頻度: ユーザーがデータをどれほど頻繁に見るかによって調整。
  3. サーバーの負荷: 高頻度なリクエストはサーバーに大きな負担をかけるため、APIプロバイダーの推奨設定を確認する。
  4. ネットワークの制限: ポーリング頻度が高いと、帯域幅の制限やコストに影響する場合があります。

推奨間隔の選び方

  • リアルタイム更新が重要な場合: 5~15秒程度(例:チャットアプリ、ライブデータ)。
  • 緊急性が低い場合: 30秒~1分程度(例:定期更新のダッシュボード)。

間隔設定の実装例


以下は、間隔を動的に設定する例です。ユーザーアクションや設定によって間隔を変更できる柔軟な設計です。

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

function DynamicPolling() {
    const [data, setData] = useState(null);
    const [intervalMs, setIntervalMs] = useState(10000); // デフォルト間隔: 10秒

    useEffect(() => {
        const fetchData = async () => {
            const response = await fetch('https://api.example.com/data');
            const result = await response.json();
            setData(result);
        };

        const intervalId = setInterval(fetchData, intervalMs);

        // クリーンアップ処理
        return () => clearInterval(intervalId);
    }, [intervalMs]); // intervalMsが変更されたら再設定

    return (
        <div>
            <h1>Dynamic Polling Example</h1>
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
            <div>
                <label>
                    Polling Interval (ms):
                    <input
                        type="number"
                        value={intervalMs}
                        onChange={(e) => setIntervalMs(Number(e.target.value))}
                    />
                </label>
            </div>
        </div>
    );
}

export default DynamicPolling;

注意点

  1. 間隔の誤設定: 1秒以下の短すぎる間隔は、クライアントとサーバーの双方に大きな負荷を与える可能性があります。
  2. バックオフ戦略: エラー発生時にはポーリング間隔を一時的に延長する「バックオフ」アルゴリズムを適用することを推奨します。

バックオフ例

let retryCount = 0;

const fetchDataWithBackoff = async () => {
    try {
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();
        setData(result);
        retryCount = 0; // 成功時はリトライ回数をリセット
    } catch (error) {
        retryCount++;
        setIntervalMs(Math.min(30000, 5000 * retryCount)); // 最大30秒まで間隔を延長
    }
};

結論


適切な間隔を選定することは、リアルタイム性とパフォーマンスのバランスを取る上で不可欠です。データ要件、サーバー負荷、ネットワーク環境を考慮した柔軟な設定を心掛けましょう。

エラーハンドリングの実装

ポーリングでのエラーハンドリングの重要性


APIリクエスト中にエラーが発生した場合、適切に対処しないとユーザー体験が損なわれるだけでなく、無駄なリクエストが繰り返されてサーバーやネットワークに負荷を与える可能性があります。ポーリングのエラーハンドリングは、システムの安定性を保つ上で非常に重要です。

主なエラーパターンとその対処法

  1. ネットワークエラー:
  • サーバーへの接続が失敗する場合。
  • 再試行(リトライ)またはエラーメッセージの表示で対応。
  1. HTTPエラー(4xx/5xx):
  • サーバーがクライアントのリクエストを拒否した場合(4xx)。
  • サーバー内部エラーや過負荷の場合(5xx)。
  • 状況に応じてリトライや間隔の延長を実施。
  1. データパースエラー:
  • APIレスポンスが期待通りの形式でない場合。
  • エラーログを出力し、開発者が調査できるようにする。

エラーハンドリングの実装例

以下は、ポーリングでエラー発生時にリトライやエラー表示を行う実装例です:

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

function PollingWithErrorHandling() {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [retryCount, setRetryCount] = useState(0);

    useEffect(() => {
        let isCancelled = false;

        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                if (!response.ok) {
                    throw new Error(`HTTP error! Status: ${response.status}`);
                }
                const result = await response.json();
                if (!isCancelled) {
                    setData(result);
                    setError(null); // 成功時はエラーをリセット
                    setRetryCount(0); // リトライカウントをリセット
                }
            } catch (err) {
                if (!isCancelled) {
                    setError(err.message);
                    setRetryCount((prev) => prev + 1); // リトライカウントを増加
                }
            }
        };

        // 一定間隔でポーリング
        const intervalId = setInterval(fetchData, 5000);

        // クリーンアップ処理
        return () => {
            clearInterval(intervalId);
            isCancelled = true;
        };
    }, [retryCount]); // リトライカウントが変化したら再実行

    return (
        <div>
            <h1>Polling with Error Handling</h1>
            {error ? (
                <div>
                    <p style={{ color: 'red' }}>Error: {error}</p>
                    <p>Retrying... (Attempt: {retryCount})</p>
                </div>
            ) : (
                data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>
            )}
        </div>
    );
}

export default PollingWithErrorHandling;

コードのポイント

  1. HTTPエラーチェック: response.okでステータスコードを検証し、エラー時は明確なメッセージをスロー。
  2. リトライロジック: retryCountでエラー後の再試行を制御。リトライ回数が多すぎる場合はバックオフ戦略を検討。
  3. エラー表示: ユーザーがエラー内容を把握できるよう、UIにエラーメッセージを表示。

リトライとバックオフ戦略


エラーが頻繁に発生する場合、以下のような戦略を採用すると効果的です:

1. エラー後に間隔を延長


エラーが続くたびにポーリング間隔を徐々に長くします:

setInterval(fetchData, Math.min(30000, 5000 * retryCount));

2. 最大リトライ回数の設定


無限にリトライするのを防ぐため、最大回数を設定します:

if (retryCount > 5) {
    clearInterval(intervalId);
}

結論


適切なエラーハンドリングにより、ポーリングの信頼性と安定性を確保できます。リトライロジックやユーザーへのフィードバックを組み込むことで、エラー発生時でもスムーズなユーザー体験を提供しましょう。

ポーリングを中止する方法

ポーリングの中止が必要な理由


ポーリングは一定間隔でAPIにリクエストを送るため、不要な場合には必ず停止する必要があります。これを怠ると、以下のような問題が発生する可能性があります:

  • 不要なサーバー負荷: 利用しないリソースへの過剰なリクエスト。
  • パフォーマンス低下: クライアント側で不要な処理が続き、アプリケーション全体のパフォーマンスが低下。
  • メモリリーク: クリーンアップ処理を適切に行わないと、不要なリソースが解放されずメモリリークが発生する。

useEffectのクリーンアップでの中止


ReactのuseEffectフックを利用してポーリングを実装する際、タイマーやリクエストの中止を確実に行うためにクリーンアップ処理を組み込む必要があります。

基本例


以下は、コンポーネントのアンマウント時にポーリングを中止する例です:

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

function PollingWithCleanup() {
    const [data, setData] = useState(null);

    useEffect(() => {
        let isCancelled = false; // ポーリング中止用のフラグ

        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                if (!response.ok) {
                    throw new Error(`HTTP error! Status: ${response.status}`);
                }
                const result = await response.json();
                if (!isCancelled) {
                    setData(result);
                }
            } catch (error) {
                console.error('Fetch error:', error);
            }
        };

        const intervalId = setInterval(fetchData, 5000); // 5秒間隔でポーリング

        // クリーンアップ処理
        return () => {
            clearInterval(intervalId); // タイマーを解除
            isCancelled = true; // フラグを立ててリクエストを無効化
        };
    }, []); // 初回レンダリング時のみ実行

    return (
        <div>
            <h1>Polling with Cleanup</h1>
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
        </div>
    );
}

export default PollingWithCleanup;

条件に基づいたポーリングの中止


ポーリングを動的に停止する必要がある場合、状態を利用して条件を管理できます。

例: ボタンでポーリングを開始/停止する

function ToggleablePolling() {
    const [data, setData] = useState(null);
    const [isPolling, setIsPolling] = useState(false);

    useEffect(() => {
        if (!isPolling) return;

        let isCancelled = false;

        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                const result = await response.json();
                if (!isCancelled) {
                    setData(result);
                }
            } catch (error) {
                console.error('Fetch error:', error);
            }
        };

        const intervalId = setInterval(fetchData, 5000);

        return () => {
            clearInterval(intervalId);
            isCancelled = true;
        };
    }, [isPolling]); // isPollingが変更されたら再実行

    return (
        <div>
            <h1>Toggleable Polling</h1>
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
            <button onClick={() => setIsPolling(!isPolling)}>
                {isPolling ? 'Stop Polling' : 'Start Polling'}
            </button>
        </div>
    );
}

ポイント

  1. クリーンアップ処理を徹底: clearIntervalなどでタイマーを解除すること。
  2. 動的な条件管理: 状態変数やフラグでポーリングを制御する設計を行う。
  3. 不要なリクエストの防止: コンポーネントがアンマウントされた場合や条件が変化した場合には、リクエストを中止する。

結論


ポーリングを中止するための適切な処理を組み込むことで、効率的かつ安定したアプリケーションを実現できます。useEffectのクリーンアップ機能や状態を活用し、必要に応じて柔軟にポーリングを停止できる設計を心掛けましょう。

カスタムフックでポーリングを管理する

カスタムフックを使うメリット


Reactのカスタムフックを利用することで、ポーリングロジックを再利用可能な形で抽象化できます。これにより、コードの可読性とメンテナンス性が向上し、複数のコンポーネントで簡単にポーリングを利用できます。

カスタムフックの実装例


以下は、カスタムフックを使用してポーリングを管理する例です。ポーリング間隔やAPIエンドポイントを柔軟に設定できる設計になっています。

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

function usePolling(fetchFunction, intervalMs, startPolling = true) {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [isPolling, setIsPolling] = useState(startPolling);
    const intervalIdRef = useRef(null);

    useEffect(() => {
        if (!isPolling) return;

        const fetchData = async () => {
            try {
                const result = await fetchFunction();
                setData(result);
                setError(null);
            } catch (err) {
                setError(err.message);
            }
        };

        // ポーリング開始
        fetchData(); // 初回実行
        intervalIdRef.current = setInterval(fetchData, intervalMs);

        // クリーンアップ処理
        return () => {
            clearInterval(intervalIdRef.current);
        };
    }, [fetchFunction, intervalMs, isPolling]);

    // ポーリングの制御を返す
    return { data, error, isPolling, start: () => setIsPolling(true), stop: () => setIsPolling(false) };
}

使い方


このカスタムフックを利用して、シンプルなポーリング機能をコンポーネントで実装します。

function PollingComponent() {
    const fetchFunction = async () => {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }
        return response.json();
    };

    const { data, error, isPolling, start, stop } = usePolling(fetchFunction, 5000);

    return (
        <div>
            <h1>Polling with Custom Hook</h1>
            {error ? (
                <p style={{ color: 'red' }}>Error: {error}</p>
            ) : data ? (
                <pre>{JSON.stringify(data, null, 2)}</pre>
            ) : (
                <p>Loading...</p>
            )}
            <button onClick={isPolling ? stop : start}>
                {isPolling ? 'Stop Polling' : 'Start Polling'}
            </button>
        </div>
    );
}

コード解説

1. **柔軟なフェッチ関数**


fetchFunctionを引数として受け取ることで、任意のAPIリクエストに対応可能。

2. **ポーリングの制御**


isPollingでポーリングの状態を管理し、startstop関数で動的に制御可能。

3. **useRefによるタイマー管理**


useRefを使うことで、setIntervalのIDを安全に保持し、適切なタイマー制御を実現。

応用例


複数のコンポーネントで同じカスタムフックを使用し、異なるAPIや間隔でポーリングを実装できます。例えば、次のようなケースで活用できます:

  • チャットメッセージの更新。
  • ダッシュボードデータの定期更新。
  • 通知のリアルタイム取得。

注意点

  1. エラーハンドリング: フェッチ関数内で適切なエラーチェックを行い、予期しない動作を防ぐ。
  2. 不要なポーリングの停止: 必要のない場合にポーリングを停止することで、リソースの無駄を防ぐ。
  3. 依存関係の管理: useEffectの依存配列に正確な値を指定し、不必要な再レンダリングを避ける。

結論


カスタムフックを使うことで、ポーリングロジックを簡潔に再利用可能な形で実装できます。これにより、アプリケーション全体のコードが整理され、複数のシナリオで効率的にポーリングを利用できます。

パフォーマンス最適化のポイント

ポーリングが引き起こすパフォーマンスの課題


ポーリングは、定期的にサーバーへリクエストを送るため、アプリケーションやサーバーのパフォーマンスに影響を与える可能性があります。特に、頻繁なリクエストや非効率なデータ処理は次のような問題を引き起こします:

  • サーバーへの過剰な負荷
  • ネットワーク帯域の浪費
  • クライアントのパフォーマンス低下

これらを防ぐために、ポーリングのパフォーマンスを最適化するいくつかの戦略を見ていきます。

最適化ポイント

1. 適切なポーリング間隔の設定


ポーリング間隔を適切に設計することが最初のステップです。更新頻度が高いデータには短い間隔(例:5秒)、それ以外には長めの間隔(例:30秒以上)を設定します。さらに、データの重要性に応じて動的に間隔を変更する設計も有効です。

2. 増分データフェッチの活用


毎回すべてのデータを取得するのではなく、サーバー側で変更された部分だけを提供する仕組みを活用しましょう。これにより、転送データ量を減らし効率的な通信が可能になります。

3. リクエストのキャンセル


最新のリクエスト以外は不要となる場合、途中のリクエストをキャンセルする仕組みを導入します。
例:AbortControllerを使用して、Reactでフェッチリクエストを中断する:

const controller = new AbortController();
fetch('https://api.example.com/data', { signal: controller.signal });
// 中断する場合
controller.abort();

4. キャッシュの利用


同じデータを何度も取得することを防ぐため、クライアント側でキャッシュを利用しましょう。React QueryやSWRなどのライブラリを使用すると、キャッシュを簡単に管理できます。

5. エラー時のバックオフ戦略


エラーが発生した場合、ポーリング間隔を一時的に延長する「エクスポネンシャルバックオフ」を実装することで、無駄なリトライを防ぎます。

let retryCount = 0;
const backoffInterval = Math.min(30000, 5000 * 2 ** retryCount);

6. リクエストのデバウンスとスロットリング


デバウンスやスロットリングを活用して、リクエストの発生頻度を抑制します。

7. コンポーネントのレンダリング最適化


ポーリングで取得したデータを使って必要な部分だけを更新するように設計します。ReactのuseMemouseCallbackを活用して、不要なレンダリングを抑制します。

React Queryを活用した最適化例


React Queryを利用することで、ポーリングやキャッシュ管理が簡単になります。

import { useQuery } from 'react-query';

function PollingWithReactQuery() {
    const { data, error, isLoading } = useQuery(
        'fetchData',
        () => fetch('https://api.example.com/data').then(res => res.json()),
        {
            refetchInterval: 5000, // ポーリング間隔を設定
            staleTime: 10000, // データが新鮮と見なされる期間
            retry: 3, // リトライ回数
        }
    );

    if (isLoading) return <p>Loading...</p>;
    if (error) return <p>Error: {error.message}</p>;

    return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

注意点

  1. 過剰なポーリングを避ける: 更新の必要がない場合、ポーリングを停止する設計を組み込みます。
  2. サーバー側の負荷を意識: サーバーが高負荷になりすぎないよう、APIプロバイダーの推奨設定を確認しましょう。

結論


ポーリングのパフォーマンス最適化には、間隔設定、キャッシュ、バックオフ戦略、そしてReact Queryのようなツールの活用が鍵となります。これらを適切に実装することで、リアルタイムデータ取得を効率的に行い、ユーザー体験を向上させることができます。

外部ライブラリを利用したポーリング

外部ライブラリを活用するメリット


ReactのuseEffectを利用してポーリングを実装することも可能ですが、外部ライブラリを使うことで以下のような利点があります:

  • シンプルで短いコード: ライブラリがポーリングやキャッシュの管理を抽象化。
  • エラー処理の自動化: 標準でリトライやバックオフ戦略をサポート。
  • パフォーマンスの向上: キャッシュ管理やデータの整合性を自動で担保。

以下に、代表的な外部ライブラリであるReact QueryとSWRを利用したポーリングの方法を紹介します。

React Queryでのポーリング


React Queryは、データフェッチやキャッシュ管理、ポーリングなどを効率的に行えるライブラリです。

import { useQuery } from 'react-query';

function PollingWithReactQuery() {
    const fetchData = async () => {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }
        return response.json();
    };

    const { data, error, isFetching } = useQuery(
        'pollingData', // クエリキー
        fetchData, // フェッチ関数
        {
            refetchInterval: 5000, // 5秒間隔でポーリング
            retry: 3, // 最大リトライ回数
            staleTime: 10000, // データを新鮮と見なす期間
        }
    );

    if (error) return <p>Error: {error.message}</p>;

    return (
        <div>
            <h1>Polling with React Query</h1>
            {isFetching && <p>Fetching new data...</p>}
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
        </div>
    );
}

ポイント

  • refetchInterval: ポーリング間隔を設定。
  • retry: エラー時の自動リトライ回数を指定。
  • staleTime: キャッシュデータの有効期間を設定。

SWRでのポーリング


SWRは軽量でシンプルなデータフェッチライブラリで、ポーリング機能も標準で提供されています。

import useSWR from 'swr';

const fetcher = (url) => fetch(url).then((res) => res.json());

function PollingWithSWR() {
    const { data, error, isValidating } = useSWR(
        'https://api.example.com/data', // APIエンドポイント
        fetcher, // フェッチ関数
        {
            refreshInterval: 5000, // ポーリング間隔
            revalidateOnFocus: false, // フォーカス時の再検証を無効化
        }
    );

    if (error) return <p>Error: {error.message}</p>;

    return (
        <div>
            <h1>Polling with SWR</h1>
            {isValidating && <p>Fetching new data...</p>}
            {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
        </div>
    );
}

ポイント

  • refreshInterval: ポーリング間隔を設定。
  • revalidateOnFocus: ページフォーカス時のデータ再検証を制御。

React QueryとSWRの比較

特徴React QuerySWR
機能の豊富さ高い(キャッシュやリトライ管理が充実)シンプルで直感的
キャッシュ管理高度な制御が可能自動管理
学習曲線やや高い低い

結論


外部ライブラリを活用することで、ポーリングの実装が大幅に簡略化されます。特にReact QueryやSWRは、効率的なデータフェッチ、キャッシュ管理、ポーリングを提供し、コードの再利用性とパフォーマンスを向上させる強力なツールです。アプリケーションの要件に応じて、適切なライブラリを選択しましょう。

まとめ

本記事では、ReactにおけるuseEffectを用いた外部APIのポーリングの方法から、効率的な実装のためのベストプラクティスを解説しました。ポーリングの基本概念やuseEffectでの実装、適切な間隔の設定、エラーハンドリング、カスタムフックの利用、さらにReact QueryやSWRといった外部ライブラリによる実装例まで網羅しました。

効率的なポーリングには、パフォーマンス最適化やリソース管理が不可欠です。適切な間隔の設定やエラー時のバックオフ戦略、キャッシュの活用を組み込むことで、安定したリアルタイム更新を実現できます。また、外部ライブラリの活用により、よりシンプルかつ信頼性の高いポーリングが可能です。

これらの知識を活用し、Reactアプリケーションでのリアルタイムデータ取得をより効果的に設計してください。

コメント

コメントする

目次