反跳における非同期要求の探索

18495 ワード

このポストでは、私は反跳で非同期の質問を見ます.どのようなライブラリが可能であり、どのようにシームレスに反応とブレンドを示します.
行きましょう!

何が反則ですか?
反跳は、状態を対応するコンポーネントにマップする状態管理ライブラリです.状態が非同期の場合、セレクタはデータフローグラフ内の純粋な関数のように振る舞う.プログラミングインターフェイスはおなじみのままですが、値の代わりに約束を返します.
消費するコンポーネントget 同期クエリのように感じるセレクタ関数から必要なもの.これは、反応サスペンス、キャッシュ、およびプリフェッチのリクエストを介してローダのような強力なテクニックを使用することができます.

設定する
あなたはsample code for this article on GitHub . 私は、あなたがこの州の図書館のより良い感じを得るためにそれをクローンして、走らせることを勧めます.使いましたjson-server クジラ種のデータをホストする.アプリロード可能なクジラのリストをロードし、より多くの情報を得るために1つを選択することができます.Ajaxの要求は、このアプリでは、状態を復元するコンポーネントを反応させるマップの非同期状態を回復します.
私は非常に大きくサンプルコードを参照されます.アプリを起動するにはnpm run json-server and npm start . APIの応答で3秒の遅延があります.あなたはpackage.json データをホストする遅延と3001ポート番号を見るには.集合するproxy to http://localhost:3001 . これは、作成するアプリをどこからAsyncデータを取得する知っている反応を作成できます.コードはルートのようなルートを参照します/whales/blue_whale , ホスト名やポート番号のノイズなし.

サスペンス反応
The <Suspense /> コンポーネントは、読み込みデータを読み込み、読み込み状態を定義するのを待ちます.状態が非同期のとき、反跳フックはこの反応成分にフックします.非同期リクエストがサスペンスに包まれない場合、ライブラリはコンパイルに失敗します.経由で回避策があるuseRecoilValueLoadable , しかし、これは州を追跡するより多くのコードが必要です.
Retilは次のようにサスペンスコンポーネントに依存できます.
<RecoilRoot>
  <Suspense fallback={<div>Loading whale types...</div>}>
    <CurrentWhaleTypes />
    <Suspense fallback={
      <div>Loading <CurrentWhaleIdValue /> info...</div>
    }> {/* nested */}
      <CurrentWhalePick />
    </Suspense>
  </Suspense>
</RecoilRoot>
The fallback ローダコンポーネントを宣言します.これは、別のコンポーネントであるかもしれません.ローダは入れ子にすることができますので、一度に1つのローダだけが表示され、これは宣言して、アプリケーションのデータロード時に定義されます.
ときに1つのクジラと<CurrentWhalePick /> ロードを開始します<CurrentWhaleIdValue /> コンポーネント内部fallback ローダー
function CurrentWhaleIdValue() {
  const whaleId = useRecoilValue(currentWhaleIdState)

  return (
    <span>{whaleId.replace('_', ' ')}</span>
  )
}
The currentWhaleIdState このクエリパラメータに対する真理の源である反跳原子です.クジラを捕まえることはクジラID状態をセットします、そして、これはローダで現れている値です.私はあなたを見てcurrentWhaleIdState が定義されているのは、これがキャッシュリクエストに対してCREILによって使用される依存であるからです.
The CurrentWhalePick コンポーネントは、クエリセレクタを介して非同期状態を取得します.反跳するuseRecoilValue 最初のリクエストを起動し、コンポーネントがラップされていない場合に例外をスローするフック<Suspense /> .
何が良いことは、これは同じですuseRecoilValue フックは同期データでセレクタを呼び出すために使用できます.つの重要な違いは、同期呼び出しがサスペンスコンポーネントのまわりでラップされる必要はないということです.
function CurrentWhalePick() {
  const whale = useRecoilValue(currentWhaleQuery) // fire AJAX request

  return (
    <>
      {whale === undefined
        ? <p>Please choose a whale.</p> // zero-config
        : <>
            <h3>{whale.name}</h3>
            <p>Life span: {whale.maxLifeSpan} yrs</p>
            <p>Diet: {whale.diet} ({whale.favoriteFood})</p>
            <p>Length: {whale.maxLengthInFt} ft</p>
            <p>{whale.description}</p>
            <img alt={whale.id} src={whale.imgSrc} />
          </>
      }
    </>
  )
}
鯨がundefined , アプリはゼロの設定状態です.すべての負荷の後、それは何が次に何をするかをユーザに示すために良いです、そして、反跳状態はこれを簡単にします.

キャッシング
CRERIALセレクタ関数はidemsibleです.asyncリクエストでは、レスポンスがキャッシュされるので、これは非常に重要になります.
セレクタ関数get パラメータの依存関係は、自動的にレスポンス値をキャッシュします.コンポーネントが同じ入力を要求したとき、セレクタはキャッシュされた値で満たされる約束を返します.
これは反則が要求を起動し、自動的にレスポンスをキャッシュする方法です.
const currentWhaleQuery = selector({
  key: 'CurrentWhaleQuery',
  get: ({get}) =>
    get(whaleInfoQuery(get(currentWhaleIdState)))
})
クエリパラメータcurrentWhaleIdState は原始文字列型を返すアトムです.Recoilは、それがキャッシュキールックアップテーブルをセットするとき、基本的な平等チェックをします.このパラメータ依存性が複雑な型のために交換されるならば、等値演算子はキーを認識しません.これは、JavaScriptの等価性チェックが同じインスタンスを探すので、オブジェクトがインスタンス化されるたびに変更されます.Recoilでの状態の突然変異は不変です.複雑な型への変更は新しいインスタンスを設定します.
つの勧告は、キャッシュを有効にするプリミティブ型としてパラメーターを設定することです.
あなたが実行しているアプリと一緒に従っている場合は、まず、ブルークジラ初めての負荷に3秒かかる.別のクジラをクリックすると、あまりにも時間がかかりますが、最初のピックをクリックすると、即座にロードされます.これは仕事中の反跳キャッシュ機構です.
クジラIDがこのデータの真実の源である原子であることを思い出してください.一旦この1つの事実が反動状態の中でセットされるならば、一貫していて、同じ意図でもう一つのパラメタを導入するのを避けることは重要です.

プリフェッチリクエスト
反跳は、クリックのようなイベントが発生するとすぐに要求を呼び出すことが可能になります.コンポーネントが新しいクジラIDパラメーターで再レンダリングするまで、Responseコンポーネントライフサイクルでクエリは実行されません.これにより、ClickイベントとAJAX要求の間に小さな遅延が発生します.ネットワーク上の非同期クエリが遅い場合は、できるだけ早く操作を開始することが有益です.
クエリをプリフェッチ可能にするには、selectorFamily 平野の代わりにselector :
const whaleInfoQuery = selectorFamily({
  key: 'WhaleInfoQuery', // diff `key` per selector
  get: whaleId => async () => {
    if (whaleId === '') return undefined

    const response = await fetch('/whales/' + whaleId)
    return await response.json()
  }
})
このセレクタ関数は単一のwhaleId パラメータget 前のセレクタで.このパラメータはcurrentWhaleIdState 原子.The key 各セレクタでは異なりますが、クジラIDパラメータは同じです.
このwhaleInfoQuery セレクタは、それを持っているので、クジラをクリックするとすぐにリクエストを発射することができますwhaleId 関数パラメータとして.
次に、イベントハンドラーはe イベントパラメータ:
function CurrentWhaleTypes() {
  const whaleTypes = useRecoilValue(currentWhaleTypesQuery)

  return (
    <ul>
      {whaleTypes.map(whale =>
        <li key={whale.id}>
          <a
            href={"#" + whale.id}
            onClick={(e) => {
              e.preventDefault()
              changeWhale(whale.id)
            }}
          >
            {whale.name}
          </a>
        </li>
      )}
    </ul>
  )
}
このコンポーネントはクジラのリストをレンダリングします.応答をループし、アンカーHTML要素にイベントハンドラを設定します.The preventDefault プログラムは、実際のURLリンクのような要素を扱うことからブラウザをブロックします.
The changeWhale 関数は、選択した要素からクジラIDをグラブし、これを新しいパラメータにする.フックuseSetRecoilState クジラIDパラメタも同様に突然変異するために働くことができますが、要求を少しの遅れまで遅らせます.
リクエストをプリフェッチしたいからです.changeWhale 次のようにします.
const changeWhale = useRecoilCallback(
  ({snapshot, set}) => whaleId => {
    snapshot.getLoadable(whaleInfoQuery(whaleId)) // pre-fetch
    set(currentWhaleIdState, whaleId)
  }
)
グラブsnapshot 使用set すぐに状態をつぶして呼び出しgetLoadable クエリとパラメータを使用して要求を呼び出します.間の順序set and getLoadable 問題ないwhaleInfoQuery 既に必要なパラメータを持つクエリを呼び出します.The set コンポーネントの再レンダリング時にクジラIDへの突然変異を保証します.
このプリフェッチを証明するには、whaleInfoQuery 正しくfetch が呼び出されます.呼び出しスタックを調べてCurrentWhaleTypes スタックの下部にあるonClick イベント.それが起こるならばCurrentWhalePick , リクエストはクリックイベントで再表示されずに発火しました.
プリフェッチと再レンダリングの間のクエリのスワッピングはuseSetRecoilState and changeWhale . githubのrepoは交換可能コードをコメントアウトした.私はこれで遊ぶことをお勧めします:スワップを再レンダリングし、コールスタックを見てください.プリフェッチに戻ると、Clickイベントからクエリが呼び出されます.

総括する
これは、最終的なデモアプリケーションのようです.

要約すると、Recoilはいくつかの優れた非同期状態機能を持っています.次のことが可能になります.
  • Aを介して反応サスペンスとのシームレスな統合<Suspense /> ラッパとフォールバックコンポーネントの読み込み中に表示する
  • セレクタ機能が無効であると仮定する自動データキャッシング
  • ボタンのようなイベントが発生するとすぐに発生します
  • 私はあなたが反跳で非同期のクエリを介してこの実行を楽しんできたことを願って、それはあなたにこのエキサイティングなライブラリを探索するいくつかのインスピレーションを与えられている!
    あなたがこのポストが好きであるならば.subscribe to our new JavaScript Sorcery list よりマジカルなJavaScriptのヒントやトリックに毎月の深いダイビングのため.
    P . P . S .あなたのノードにAPMが必要な場合.JSアプリcheck out the AppSignal APM for Node.js .
    Camiloはヒューストン、テキサスからのソフトウェアエンジニアです.彼はJavaScriptとドラマなしで実行されるクリーンなコードに情熱的です.コーディングされていないとき、彼は調理し、ランダムなホームプロジェクトに取り組んで大好きです.