目次
サスペンスクイックスタート
いくつかの画像をプリロードしましょう!
達成
トランジションステータスの更新
インターネットの滝は避けてください
遅延ハング
デモ
その他
ホームページ ウェブフロントエンド CSSチュートリアル React Suspenseを使用した事前キャッシュ画像

React Suspenseを使用した事前キャッシュ画像

Apr 02, 2025 pm 06:14 PM

React Suspenseを使用した事前キャッシュ画像

Reactのサスペンス機能はエキサイティングであり、それが来ており、開発者は「準備ができている」までコンポーネントのレンダリングを簡単に遅らせることができ、よりスムーズなユーザーエクスペリエンスになります。 「準備」はここで多くの側面を指すことができます。たとえば、データロードユーティリティをサスペンスと組み合わせて使用​​して、クエリごとに負荷ステータスを手動で追跡せずにデータが転送されている間に、一貫した負荷ステータスを表示できます。次に、データが利用可能で、コンポーネントが「準備ができている」とレンダリングされます。これは、サスペンスで最も頻繁に議論されるトピックであり、私は以前にそれについて書いたことがあります。ただし、データの読み込みは、サスペンスがユーザーエクスペリエンスを改善できる多くのユースケースの1つにすぎません。今日話したい別のユースケースは、画像のプリロードです。

画像がダウンロードされ、画面に到達したときにレンダリングされたときにポジションが不安やジャンプするWebアプリを作成または使用したことがありますか?私たちはそれをコンテンツの再配置と呼び、それは衝撃的で不快なものです。サスペンスはこの問題を解決するのに役立ちます。サスペンスの全体的なポイントは、コンポーネントのレンダリングが準備が整うことを防ぐことだと言ったことをご存知ですか?幸いなことに、「Ready」はここで非常に開かれています - 私たちの目的のために、「必要なプリロードされた画像」を含めることができます。それをする方法を見てみましょう!

サスペンスクイックスタート

詳細を掘り下げる前に、サスペンスがどのように機能するかをすぐに理解しましょう。 2つの主要な部分があります。まず、コンポーネントハングの概念があります。これは、Reactがコンポーネントをレンダリングしようとしていることを意味しますが、「準備ができている」わけではありません。これが起こると、コンポーネントツリーで最も近い「フォールバック」がレンダリングされます。すぐにフォールバックを作成する方法(これはかなり単純です)を確認しますが、コンポーネントは、まだ準備ができていないことをReactに伝えています。 Reactは約束をキャプチャし、コンポーネントがまだ準備ができていないことを認識し、フォールバックをレンダリングします。約束の場合、Reactは再びレンダリングを試みます。このプロセスを繰り返します。はい、私は少し単純化されていますが、それがサスペンスがどのように機能するかという点であり、私たちはこれらの概念のいくつかを拡張します。

サスペンスの2番目の部分は、「トランジション」ステータスアップデートの導入です。これは、状態を設定することを意味しますが、Reactに状態の変化がコンポーネントを掛ける原因となる可能性があり、これが発生した場合、フォールバックはレンダリングされないことを伝えます。代わりに、ステータスの更新が準備されるまで現在の画面を表示し続け、その時点でレンダリングします。もちろん、Reactは、インライン負荷フィードバックを提供できるように、このプロセスが進行中であることを開発者に知らせる「保留中の」ブールインジケーターを提供します。

いくつかの画像をプリロードしましょう!

まず、この記事の最後に作成している完全なデモがあることを指摘したいと思います。コードにジャンプしたい場合は、今すぐデモを開いてください。遷移状態の更新と組み合わせてサスペンスがどのように使用されるかを示し、画像をプリロードします。この投稿の残りの部分では、コードを段階的に構築し、途中で方法と理由を説明します。

わかりました、始めましょう!

すべての画像がプリロードされるまで、コンポーネントを掛けたいと考えています。操作を可能な限り簡素化するには、<suspenseimage></suspenseimage> SRC属性を受信するコンポーネントは、画像をプリロードし、例外スローを処理してから、 <img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174358885649082.png" class="lazy" alt="React Suspenseを使用した事前キャッシュ画像"> HTMLで画像を使用しますが、JavaScriptのImage()オブジェクトを使用して命令的な方法で画像を作成することもできます。さらに、この方法で作成する画像には、画像がロードされたときに発火するonloadコールバックがあります。このように見えます:

 const img = new Image();
img.onload =()=> {
  //画像が読み込まれます};
ログイン後にコピー

しかし、どのようにしてそれを例外スローと組み合わせるのでしょうか?あなたが私のようであれば、あなたは最初にこのようなことを考えるかもしれません:

 const suspenseimg =({src、... rest})=> {
  新しい約束を投げる((解決)=> {
    const img = new Image();
    img.onload =()=> {
      解決する();
    };
    img.src = src;
  });
  戻る<img alt="" src="%7Bsrc%7D">;
};
ログイン後にコピー

もちろん、問題は、これが常に約束を投げかけることです。 Reactがレンダリングを試みるたびに<suspenseimg></suspenseimg>インスタンスが進行中の場合、新しい約束が作成され、すぐにスローされます。代わりに、画像がロードされる前に約束を投げたいだけです。間接的な層を追加することでコンピューターサイエンスのすべての問題を解決できるという古いことわざがあります(間接の層が多すぎるという問題を除く)。 SRCを読むと、キャッシュが画像をロードしたかどうかを確認します。そうでない場合は、プリロードを開始して例外をスローします。そして、画像がプリロードされている場合、それは単にtrueを返し、Reactが画像をレンダリングし続けます。

これは私たちのものです<suspenseimage></suspenseimage>コンポーネントがどのように見えるか:

 const suspenseimg =({src、... rest})=> {
  imgcache.read(src);
  返品<img  src="%7Bsrc%7D" alt="React Suspenseを使用した事前キャッシュ画像" >;
};
ログイン後にコピー

これが、私たちがキャッシュした最小バージョンのように見えるものです:

 const imgcache = {
  __cache:{}、
  read(src){
    if(!this .__キャッシュ[src]){
      この.__キャッシュ[src] = new Promise((Resolve)=> {
        const img = new Image();
        img.onload =()=> {
          この.__キャッシュ[src] = true;
          Resolve(this .__キャッシュ[src]);
        };
        img.src = src;
      });
    }
    if(this .__キャッシュ[src] instanceof promise){
      これを投げます。__キャッシュ[src];
    }
    これを返してください。__キャッシュ[src];
  }
};
ログイン後にコピー

完璧ではありませんが、今のところ十分です。使い続けましょう。

達成

以下は完全に機能するデモへのリンクを覚えておいてください。そのため、特定のステップで速すぎて移動しても絶望しないでください。私たちは行くように説明します。

フォールバックを定義することから始めましょう。コンポーネントツリーにサスペンスタグを配置してフォールバックを定義し、フォールバック属性を渡します。保留中のコンポーネントは、最新のサスペンスタグを検索してフォールバックをレンダリングします(ただし、サスペンスタグが見つからない場合、エラーがスローされます)。実際のアプリケーションでは、プロセス全体に多くのサスペンスタグがある場合があり、個々のモジュールの特定のフォールバックを定義しますが、このデモではルートアプリケーションをラップするタグのみが必要です。

 function app(){
  戻る (
    <suspense fallback="{<Loading"></suspense> }>
      <showimages></showimages>
    
  );
}
ログイン後にコピー

<loading></loading>コンポーネントは基本的なスピナーですが、実際のアプリケーションでは、よりシームレスなエクスペリエンスを提供するために実際にレンダリングしようとしているコンポーネントのある種の空のシェルをレンダリングしたい場合があります。

これで、私たちのもの<showimages></showimages>コンポーネントは、最終的に次のものを使用して画像をレンダリングします。

<div>
  {images.map((img)=>(
    <div key="{img}">
      <suspenseimg alt="" src="%7Bimg%7D"></suspenseimg>
    </div>
  ))}
</div>
ログイン後にコピー

最初の読み込みでは、最初の画像が準備が整うまで荷重スピナーが表示され、その時点では、インターレース再配置ラグなしで同時に表示されます。

トランジションステータスの更新

画像が配置されたら、次の画像のバッチをロードすると、ロード後に画像を表示してもらいたい場合は、もちろん、既存の画像をロードするときに画面上に保持します。これを行うためにuseTransitionフックを使用します。これにより、 startTransition関数と、ステータスの更新が進行中であるが停止されていることを示すisPending Booleanが返されます(または、停止されていない場合でも、ステータスの更新に時間がかかりすぎると真実かもしれません)。最後に、 useTransition場合、 timeoutMs値を渡す必要があります。これは最大時間です。これは、 isPendingフラグが真である可能性があります。その後、Reactはフォールバックを放棄してレンダリングします( timeoutMsパラメーターが近い将来削除される可能性があり、既存のコンテンツが更新されると、遷移状態の更新は可能な限り待機する必要があります)。

これが私がどのように見えるかです:

 const [starttransition、ispending] = usetransition({timeoutms:10000});
ログイン後にコピー

Fallbackディスプレイの前に10秒を許可します。これは実際の生活では長すぎるかもしれませんが、特に実験のためにDevtoolsのネットワークを意図的に減速させる可能性がある場合は、このデモに適しています。

これがそれを使用する方法です。より多くの画像をロードするボタンをクリックすると、コードは次のようになります。

 starttransition(()=> {
  setPage((p)=> p 1);
});
ログイン後にコピー

このステータスの更新により、GraphQLクライアントMicro-GraphQL-Reactを使用して新しいデータロードがトリガーされます。これは、サスペンスと互換性があり、クエリが進行中のときに私たちに約束を投げかけます。データが返されると、画像がプリロードされたときにコンポーネントがレンダリングと再度ハングを試みます。これはすべて発生しますが、私たちのisPending値は真実になります。これにより、既存のコンテンツの上部にロードスピナーを表示できます。

インターネットの滝は避けてください

イメージのプリロードが進行中に、どのように反応がレンダリングをブロックできるか疑問に思うかもしれません。上記のコードを使用して、これを行うとき:

 {images.map((img)=>(
ログイン後にコピー

...そしてその中にレンダリングされているもの<suspenseimage></suspenseimage>、反応は最初の画像をレンダリングし、ハングしてからリストを再試行し、最初の画像(現在はキャッシュに)を超えてから、2番目の画像、次に3番目、4番目などを掛けます。前にサスペンスについて読んだ場合は、これらすべてのレンダリングが起こる前にリスト内のすべての画像を手動でプリロードする必要があるかどうか疑問に思うかもしれません。

Reactがサスペンスの世界で物事をどのようにレンダリングするかについてはかなり賢いので、心配したり、厄介なプリロードをする必要はないことがわかります。 Reactがコンポーネントツリーを通過すると、保留中に遭遇しても停止しません。代わりに、コンポーネントツリー内の他のすべてのパスをレンダリングしようとし続けています。したがって、はい、画像0をレンダリングしようとすると、ハングが発生しますが、Reactはハングする前に画像1をnにレンダリングしようとし続けます。

これは、新しい画像セットがロードされたときに完全なデモでネットワークタブを表示することで表示できます。ネットワークリストにすぐに画像バケットが表示され、1つずつ解析され、完了した場合、結果を画面に表示する必要があります。この効果を実際に増幅するには、ネットワークの速度を「高速3G」に減らすことをお勧めします。

楽しみのために、Reactがコンポーネントをレンダリングしようとする前に、キャッシュから各画像を手動で読み取り、コンポーネントツリー内のすべてのパスを横断することにより、サスペンスに画像を通過させることができます。

 Images.foreach((img)=> imgcache.read(img));
ログイン後にコピー

これを説明するデモを作成しました。新しい画像セットをロードするときにネットワークタブを表示すると、ネットワークリストに順番に追加されていることがわかります(ただし、ネットワークを遅くしてこれを実行しないでください)。

遅延ハング

サスペンスを使用する場合、1つの推論を覚えておく必要があります。レンダリングで可能な限り遅れてコンポーネントツリーの低レベルを掛けます。一時停止された画像の束をレンダリングしている場合<imagelist></imagelist>、各画像が独自のコンポーネントに吊り下げられていることを確認して、Reactが個別にアクセスできるように、他の画像をブロックして滝をブロックしないようにします。

このルールのデータ読み込みバージョンは、実際にそれを必要とするコンポーネントによってデータを可能な限りロードする必要があるということです。これは、コンポーネントで以下を実行することを避ける必要があることを意味します。

 const {data1} = usesuspensequery(query1、vars1);
const {data2} = usesuspensequery(query2、vars2);
ログイン後にコピー

これを避けたい理由は、クエリがハングしてから2つを照会し、滝を引き起こすためです。これがまったく回避できない場合は、吊り下げる前に両方のクエリを手動でプリロードする必要があります。

デモ

これが私のコミットメントのデモンストレーションです。上記のデモと同じです。

デモを開き、実行して開発ツールを開くと、DevToolsネットワークタブに表示されているDisable Cacheボックスをチェックしてください。そうしないと、デモ全体が破損します。

コードは、私が以前に示したコードとほぼ同じです。デモの1つの改善は、キャッシュ読み取り方法に次の行があることです。

 setimeout(()=> Resolve({})、7000);
ログイン後にコピー

すべての画像を適切にプリロードしますが、実際の生活では、1つまたは2つの画像がゆっくりとロードされるという理由だけで、無期限にレンダリングをブロックしたくない場合があります。したがって、たとえ画像の準備ができていなくても、しばらくすると緑色の光を与えます。ユーザーは画像または2つの点滅が表示されますが、これはソフトウェアフリーズのフラストレーションに耐えるよりも優れています。また、7秒が長すぎる可能性があることを指摘したいと思いますが、このデモでは、ユーザーがDevToolsのネットワークを遅くして、サスペンス機能をより明確にし、できればこれをサポートする可能性があると思います。

デモには、Precache画像チェックボックスもあります。デフォルトで選択されますが、通常の使用にしてチェックすることができます<img alt="React Suspenseを使用した事前キャッシュ画像" >タグの交換<suspenseimage></suspenseimage>コンポーネント、サスペンスバージョンを「通常の反応」と比較する場合(結果が表示されたら確認しないでください。そうしないと、UI全体がハングしてフォールバックをレンダリングする場合があります)。

最後に、CodeSandboxと同様に、一部の状態が同期しない場合がある場合があるため、物事が奇妙に見えたり破損したりする場合は、更新ボタンをクリックします。

その他

このデモをまとめるとき、私は誤って大きな間違いを犯しました。ブラウザがダウンロードした画像をキャッシュするため、デモがその効果を失いたくありません。したがって、キャッシュブレーカーを使用してすべてのURLを手動で変更します。

 const [cacheBuster、setCacheBuster] = ueseState(initial_time);

const {data} = usesuspensequery(get_images_query、{page});
const images = data.allbooks.books.map(
  (b)=> b.smallimage `?cachebust = $ {cachebuster}`
);
ログイン後にコピー

Initial_timeは、モジュールレベル(つまり、グローバル)で定義されます。

 const initial_time = new date();
ログイン後にコピー

なぜ私がこれをしなかったのか疑問に思っているなら:

 const [cachebuster、setCacheBuster] = ueseState(new date());
ログイン後にコピー
ログイン後にコピー

...これは、ひどくひどい結果をもたらす可能性があるためです。最初のレンダリングでは、画像はレンダリングを試みます。キャッシュはハングを引き起こし、反応するレンダリングをキャンセルし、フォールバックを表示します。すべての約束が解析されたとき、Reactは再目的レンダリングを試みます、そして、私たちの最初のuesestateコールは再実行されます

 const [cachebuster、setCacheBuster] = ueseState(new date());
ログイン後にコピー
ログイン後にコピー

...新しい初期値で再実行され、まったく新しい画像URLがセットになります。コンポーネントが実行されることはなく、CodeSandboxデモは実行を停止します(これにより、デバッグがイライラします)。

これは、この特定のデモの独自の要件によって引き起こされる奇妙な特別な問題のようですが、より大きな教訓があります。レンダリングは純粋であり、副作用はないはずです。 Reactはコンポーネントを複数回再レンダリングしようとすることができるはずであり、(同じ初期小道具が与えられた)は、反対側から同じ状態を取得する必要があります。

以上がReact Suspenseを使用した事前キャッシュ画像の詳細内容です。詳細については、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)

粘着性のあるポジショニングとサスのダッシュを備えた積み重ねられたカード 粘着性のあるポジショニングとサスのダッシュを備えた積み重ねられたカード Apr 03, 2025 am 10:30 AM

先日、Corey Ginnivanのウェブサイトから、この特に素敵なビットを見つけました。そこでは、スクロール中にカードのコレクションが互いに積み重ねられていました。

Googleフォント変数フォント Googleフォント変数フォント Apr 09, 2025 am 10:42 AM

Google Fontsが新しいデザイン(ツイート)を展開したようです。最後の大きな再設計と比較して、これははるかに反復的です。違いをほとんど伝えることができません

HTML、CSS、JavaScriptを使用してアニメーションカウントダウンタイマーを作成する方法 HTML、CSS、JavaScriptを使用してアニメーションカウントダウンタイマーを作成する方法 Apr 11, 2025 am 11:29 AM

プロジェクトにカウントダウンタイマーが必要だったことはありますか?そのようなことのために、プラグインに手を伸ばすのは自然なことかもしれませんが、実際にはもっとたくさんあります

フレックスレイアウト内の紫色のスラッシュ領域が誤って「オーバーフロー空間」と見なされるのはなぜですか? フレックスレイアウト内の紫色のスラッシュ領域が誤って「オーバーフロー空間」と見なされるのはなぜですか? Apr 05, 2025 pm 05:51 PM

フレックスレイアウトの紫色のスラッシュ領域に関する質問フレックスレイアウトを使用すると、開発者ツールなどの混乱する現象に遭遇する可能性があります(D ...

CSSを介してファーストクラスの名前アイテムを使用して子要素を選択する方法は? CSSを介してファーストクラスの名前アイテムを使用して子要素を選択する方法は? Apr 05, 2025 pm 11:24 PM

要素の数が固定されていない場合、CSSを介して指定されたクラス名の最初の子要素を選択する方法。 HTML構造を処理するとき、あなたはしばしば異なる要素に遭遇します...

HTMLデータ属性ガイド HTMLデータ属性ガイド Apr 11, 2025 am 11:50 AM

HTML、CSS、およびJavaScriptのデータ属性について知りたいと思っていたことはすべて。

SASSをより速くするための概念の証明 SASSをより速くするための概念の証明 Apr 16, 2025 am 10:38 AM

新しいプロジェクトの開始時に、SASSコンピレーションは瞬く間に起こります。これは、特にbrowsersyncとペアになっている場合は素晴らしい気分です。

See all articles