ホームページ ウェブフロントエンド jsチュートリアル React での非同期データのフェッチとキャッシュのための軽量フックのショーケース

React での非同期データのフェッチとキャッシュのための軽量フックのショーケース

Jan 07, 2025 pm 06:36 PM

Showcase of a Lightweight Hook for Async Data Fetching & Caching in React

皆さんこんにちは!

私は useAsync と呼ばれる軽量の React フックに取り組んできました。これは React Query の重要な機能 (フェッチ、キャッシュ、再試行など) の一部を模倣していますが、よりコンパクトです。簡単にカスタマイズできるパッケージ。以下は、関連するコードセクションを参照しながら、内部でどのように動作するかを簡単に説明したものです。コード全体を確認したい場合は、リポジトリに移動してください:

GitHub 上の完全なソース コード
このフックは、npm で api-refetch としても利用できます。


なぜ独自のフックを作るのか?

React Query と SWR はどちらも優れたライブラリですが、いくつかの理由から、より実践的なアプローチが必要でした。

  1. 軽量フットプリント

    React Query と SWR は機能が豊富ですが、比較的サイズが大きくなる可能性があります (React Query ~2.2 MB、SWR ~620 kB)。 api-refetch は約 250 KB であるため、バンドル サイズが大きな懸念事項となる 小規模なアプリに最適です。このフックは、別のライブラリ (Intlayer) の依存関係としてインストールされることを意図しています。結果として、ソリューションのサイズが重要な考慮事項となりました。

  2. カスタマイズと最適化が簡単
    ローカル ストレージからのデータの保存/取得や、単純なアプローチを使用した並列リクエストの管理など、いくつかの特定の機能が必要でした。
    リポジトリを複製するか、コードをプロジェクトに直接コピーすることで、不要な機能を削除し、必要なものだけを保持できます。これにより、バンドル サイズが削減されるだけでなく、不必要な再レンダリングと増加が最小限に抑えられ、特定の要件に合わせた、より効率的でパフォーマンスの高いソリューションが得られます。

  3. 必要なプロバイダーはありません

    フックをグローバルにするためにコンテキスト プロバイダーを避け、その使用法をできるだけシンプルにしたいと考えました。そこで、Zustand ストアに基づいてフックのバージョンを作成しました (以下の例を参照)。

  4. 学習演習

    非同期ライブラリを最初から構築することは、同時実行性、キャッシュ、状態管理の内部構造を理解するための優れた方法です

要するに、独自のフックを作成することは、ライブラリを小さく理解しやすく保ちながら、必要な機能に正確に焦点を当てる (必要ない機能はスキップする) 機会でした。

対象となる機能

React フックの管理:

  • フェッチと状態管理: ロード、エラー、成功、フェッチされた状態を処理します。
  • キャッシュとストレージ: オプションでデータをキャッシュし (React 状態または内部の Zustand 経由)、ローカル ストレージのサポートを提供します。
  • 再試行と再検証: 構成可能な再試行制限と自動再検証間隔。
  • アクティブ化と無効化: 他のクエリまたは状態に応じて、クエリを自動的にアクティブ化および無効化します。例: ユーザーがログインすると一部のデータが自動的に取得され、ユーザーがログアウトするとデータが無効になります。
  • 並列コンポーネント マウント フェッチ: 複数のコンポーネントが同時にマウントされる場合、同じリソースに対する複数の同時リクエストを防ぎます。

コードの仕組み

以下は、API 再取得の重要なポイントと、useAsync.tsx のコードの関連部分への短い参照です。

1. 並列マウントの取得と処理

  • コードスニペット:
  // This map stores any in-progress Promise to avoid sending parallel requests
  // for the same resource across multiple components.
  const pendingPromises = new Map();

  const fetch: T = async (...args) => {
    // Check if a request with the same key + args is already running
    if (pendingPromises.has(keyWithArgs)) {
      return pendingPromises.get(keyWithArgs);
    }

    // Otherwise, store a new Promise and execute
    const promise = (async () => {
      setQueryState(keyWithArgs, { isLoading: true });

      // ...perform fetch here...
    })();

    // Keep it in the map until it resolves or rejects
    pendingPromises.set(keyWithArgs, promise);
    return await promise;
  };
ログイン後にコピー
ログイン後にコピー
  • 説明: ここでは、進行中のフェッチを pendingPromises マップに保存します。 2 つのコンポーネントが (同じ keyWithArgs を持つことによって) 同じリソースを同時にフェッチしようとすると、2 番目のコンポーネントは重複したネットワーク呼び出しを行う代わりに、進行中のリクエストを再利用するだけです。

2. 再検証

  • コードスニペット:
  // Handle periodic revalidation if caching is enabled
  useEffect(
    () => {
      if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled
      if (!isEnabled || !enabled) return; // Hook is disabled
      if (isLoading) return; // Fetch is already in progress
      if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate
      if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled

      const timeout = setTimeout(() => {
        fetch(...storedArgsRef.current);
      }, revalidateTime);

      return () => clearTimeout(timeout);
    },
    [
      /* dependencies */
    ]
  );
ログイン後にコピー
ログイン後にコピー
  • 説明: 再検証を有効にするたびに、API-refetch はキャッシュされたデータが指定された revalidateTime よりも古いかどうかをチェックします。有効な場合、データはバックグラウンドで自動的に再取得され、追加の手動トリガーなしで UI の同期が維持されます。

3. リトライロジック

  • コードスニペット:
  useEffect(
    () => {
      const isRetryEnabled = errorCount > 0 && retryLimit > 0;
      const isRetryLimitReached = errorCount > retryLimit;

      if (!isEnabled || !enabled) return; // Hook is disabled
      if (!isRetryEnabled) return; // Retry is disabled
      if (isRetryLimitReached) return; // Retry limit has been reached
      if (!(cacheEnabled || storeEnabled)) return; // Useless to retry if caching is disabled
      if (isLoading) return; // Fetch is already in progress
      if (isSuccess) return; // Hook has already fetched successfully

      const timeout = setTimeout(() => {
        fetch(...storedArgsRef.current);
      }, retryTime);

      return () => clearTimeout(timeout);
    },
    [
      /* dependencies */
    ]
  );
ログイン後にコピー
  • 説明: エラーが発生した場合、フックは試行が失敗した回数をカウントします。まだ retryLimit を下回っている場合は、自動的に retryTime ミリ秒待ってから再試行します。このプロセスは、データが正常にフェッチされるか、再試行制限に達するまで継続されます。

4. 自動フェッチ

  • コードスニペット:
  // Auto-fetch data on hook mount if autoFetch is true
  useEffect(
    () => {
      if (!autoFetch) return; // Auto-fetch is disabled
      if (!isEnabled || !enabled) return; // Hook is disabled
      if (isFetched && !isInvalidated) return; // Hook have already fetched or invalidated
      if (isLoading) return; // Fetch is already in progress

      fetch(...storedArgsRef.current);
    },
    [
      /* dependencies */
    ]
  );
ログイン後にコピー
  • 説明: autoFetch を true に設定すると、フックはコンポーネントがマウントされるとすぐに非同期関数を自動的に実行します。これは、ロード時に常にデータが必要な「ファイア アンド フォーゲット」シナリオに最適です。

GitHub で完全なソースを参照してください

ローカル ストレージ ロジック、クエリの無効化などが含まれる完全なコードをここで確認してください:

  • 完全なソース コード

ご興味がございましたら、お気軽に試してみたり、問題を報告したり、貢献してください。フィードバックは大歓迎です!

使用例

インストール

コードをコピーするか、(リポジトリ)[https://github.com/aymericzip/api-refetch]をコード化します

または

  // This map stores any in-progress Promise to avoid sending parallel requests
  // for the same resource across multiple components.
  const pendingPromises = new Map();

  const fetch: T = async (...args) => {
    // Check if a request with the same key + args is already running
    if (pendingPromises.has(keyWithArgs)) {
      return pendingPromises.get(keyWithArgs);
    }

    // Otherwise, store a new Promise and execute
    const promise = (async () => {
      setQueryState(keyWithArgs, { isLoading: true });

      // ...perform fetch here...
    })();

    // Keep it in the map until it resolves or rejects
    pendingPromises.set(keyWithArgs, promise);
    return await promise;
  };
ログイン後にコピー
ログイン後にコピー

簡単な例

  // Handle periodic revalidation if caching is enabled
  useEffect(
    () => {
      if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled
      if (!isEnabled || !enabled) return; // Hook is disabled
      if (isLoading) return; // Fetch is already in progress
      if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate
      if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled

      const timeout = setTimeout(() => {
        fetch(...storedArgsRef.current);
      }, revalidateTime);

      return () => clearTimeout(timeout);
    },
    [
      /* dependencies */
    ]
  );
ログイン後にコピー
ログイン後にコピー

それだけです!試してみて、どうなるか教えてください。 GitHub でのフィードバック、質問、貢献を大歓迎です。

GitHub: api-refetch

コーディングを楽しんでください!

以上がReact での非同期データのフェッチとキャッシュのための軽量フックのショーケースの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JavaScriptエンジン:実装の比較 JavaScriptエンジン:実装の比較 Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへ:すべてがどのように機能するか C/CからJavaScriptへ:すべてがどのように機能するか Apr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptとWeb:コア機能とユースケース JavaScriptとWeb:コア機能とユースケース Apr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScript in Action:実際の例とプロジェクト JavaScript in Action:実際の例とプロジェクト Apr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンの理解:実装の詳細 JavaScriptエンジンの理解:実装の詳細 Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

Python vs. JavaScript:開発環境とツール Python vs. JavaScript:開発環境とツール Apr 26, 2025 am 12:09 AM

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

See all articles