React-Queryの使用


react-Queryとは?


react-queryはswrとともにAPI通信プロセスを使用する簡単で強力なライブラリである(実際には両ライブラリともHTTPキャッシュが無効なポリシーstal-while-revalidateに着目している).公式ファイルを借りると、宣言性も簡単で、zeroconfはreact-queryの利点です.実際には,非同期論理を綿密に実施するには,綿密な管理と努力が必要である.react-queryを学び、これらのトラブルを軽減するために使用しました.

ステータスとは?


フロント開発の過程で、管理状態の仕事は本当に多いです.私たちが管理している状態は何ですか?
私が考えている状態はこうです
  • データ
  • 、特定の時間を構成するシステムに随時変更可能
  • プログラムに格納データ
  • は、文字列、配列、オブジェクト等の形式である.
    成熟したUIと優れたUXの登場に伴い、サービス規模は拡大し、コード量も増加している.
    当然、フロントエンド管理の場合も多くなり、それによって生じる様々な問題(Redux、Mobx等)の解決が考えられている.
    特にバックエンドから受信したデータは、リクエストからレスポンスまで、成功と失敗の論理の作成に追われ、レスポンス後にクライアントのステータスと同期を維持します.それでも、バックエンドで受信したデータは操作可能なデータであるため、クライアントの意図とは異なり、データが変更され、時代遅れになる可能性があります.
    この点、react-queryでは、クライアントが管理するデータと、サーバが管理するデータを分類して表示できます.
  • クライアントステータス:クライアント上で完全に動作可能な同期および最新データ.
  • ex) useState
  • サーバステータス:非同期APIによって受信されたデータを表示します.
  • クライアントが制御できないデータ
  • は私だけが操作できるわけではないので、最新を保証することはできません.=>期限切れを考慮する
  • ex)DBのデータ
  • 実際には、クライアントがサーバのステータスを同時に管理すると、storeは非常に混乱します(ステータス管理コードではなく、非同期通信コードのように見えます).私が使った方法の中で一番複雑なのはsagaです
    function* deletePost({id}) {
      try {
        yield put({ type: DELETE_POST_SUCCESS, deletePostId: id });
      } catch (err) {
        yield put({ type: DELETE_POST_ERROR, payload: err });
      }
    }
    
    function* watchAddComment() {
      yield takeLatest(DELETE_POST_REQUEST, addComment);
    }
    これは強力なミドルウェアに違いありませんが、簡単な非同期ロジックにもコード量、初期設定、カーブの実行などの問題があります.react-queryを使用することで、使いやすさと読みやすさを十分に活用できます.

    Installation

     $ npm i react-query
     # or
     $ yarn add react-query

    Before Start

    import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
     
    const queryClient = new QueryClient()
    
    export default function App() {
      return (
        <QueryClientProvider client={queryClient}>
    		<Todos />
        </QueryClientProvider>
      )
    }
    react-queryを使用すると、サーバステータスがグローバルに管理されているように感じます.Providerは気づいたかもしれませんが、実際にreact-queryはreactが提供するコンテキストに基づいて作成され、データを管理します.

    react-queryを使用して表示


    Queries

    import { useQuery } from 'react-query'
     
    function App() {
      const info = useQuery('todos', fetchTodoList, options)
    }
  • userQueryのパラメータは、key、promiseの関数とオプションを返す必要があります.
  • useQueryは、データ、error、isError、isLoading、isSuccess、refretch、statusなどを返す.
  • options
  • enable:falseに設定されている場合、クエリーは自動的に呼び出されません.すなわち、最初の宣言時にコールを阻止することができる.
  • 再試行:要求が失敗した場合に再試行要求を実行します.既定値は3です.
  • Refect Interval:一定の間隔でRefectを行うことができます.
  • RefectOnMount:マウント時にRefectを行うかどうかを決定します.trueの場合は、古い状態で再構築されます.(booelan | "always")
  • 古い:データがいつ古いかを決定します.既定値は0です.
  • cacheTime:キャッシュされたデータはメモリの残り時間を決定します.デフォルトは5分(5*60*1000)です.
  • に加えて、さまざまなオプションがあります.公式文書を確認しましょう!
  • 上のオプションから、見慣れないオプションがいくつか存在することがわかります(stageは何ですか、cacheTimeは何ですか?refetchOnMountはtrueですか、falseですか、allyは何ですか?)よりよく理解するために、reaction-queryのコアコンテンツを理解してみましょう.
    Queryのライフサイクル
    queryには大体5つの状態があります.
    順番にキャプチャ>fresh>時代遅れ>非アクティブ>削除
    fresh<-->stan:新鮮または古い状態で行います.
  • の最初のクエリがキャプチャ状態として宣言された場合.
  • 以降からデータを受信した場合、上記のオプションで指定した古い時間が期限切れになる前に、「新鮮」とみなされます.ただし、何も設定しない場合、[タイムアウト](Time Of Time)は0になるため、すぐに[タイムアウト](Time Of Time)になります.
  • fresh状態で期限が切れた場合、この状態は時代遅れになります.
  • queryがアンインストールされると、非アクティブになります.
  • cacheTimeが
  • 以降で期限切れ(5分)になった場合、GCはメモリからデータを削除し、削除します.
  • queryはこれらのストリームを使用して行います.
    たとえば、queryオプションが{refretchOnMount:[常に]に設定されている場合、このオプションはキャプチャ後5秒以内に新鮮な状態に保たれます.5秒後には古い状態になります.クエリが5秒以内に>mountでアンインストールされている場合、refectOnMountオプションは「常に」であるため、fresh状態になりますが、refectが発生します.

    Query Keys


    userQueryで使用されるキーはqueryを識別する一意の値であり、stringとarrayの2種類しか使用できません.
    string
    useQuery('todos', ...) // queryKey === ['todos']
    ただしstringは内部で単一配列に変換されます.
    array
    クエリー・データ識別に他の情報が必要な場合は、鍵を配列として提供できます.
    useQuery(['todo', 5], ...)
     
    useQuery(['todo', 5, { preview: true }], ...)
    ただし、配列順によっては、すべてのキーが単一のキーとみなされます.
    useQuery(['todos', status, page], ...)
    useQuery(['todos', page, status], ...)
    //not equal

    Parallel Queries


    複数のクエリーを宣言する必要がある場合でも、他のスキルを宣言する必要はありません.react-queryは内部で並列に処理されます.
    function App () {
       const usersQuery = useQuery('users', fetchUsers)
       const teamsQuery = useQuery('teams', fetchTeams)
       const projectsQuery = useQuery('projects', fetchProjects)
       ...
     }

    Queries Syncronization


    たとえば、Aというコンポーネントからtodoqueryを呼び出し、Bというコンポーネントからtodoqueryを呼び出すとどうなりますか.APIは再び呼び出されますか?正解は「queryが古い場合にのみAPIが呼び出される」です.fresh状態の場合、API呼び出し自体は発生しません.古いクエリは、再エッチング後にAおよびB要素に最新の状態で渡されます.

    Mutations


    前述したqueryがデータの取得に注目している場合、variantはcreate/update/deleteに使用することを推奨します.
    function App() {
       const mutation = useMutation(newTodo => {
         return axios.post('/todos', newTodo)
       })
     
       return (
         <div>
           {mutation.isLoading ? (
             'Adding todo...'
           ) : (
             <>
               {mutation.isError ? (
                 <div>An error occurred: {mutation.error.message}</div>
               ) : null}
     
               {mutation.isSuccess ? <div>Todo added!</div> : null}
     
               <button
                 onClick={() => {
                   mutation.mutate({ id: new Date(), title: 'Do Laundry' })
                 }}
               >
                 Create Todo
               </button>
             </>
           )}
         </div>
       )
     }
    その使用は非常に直感的で、useQueryと同様に多くの異なるPropertyを返しているので、使いやすいです.

    Mutation Side Effects


    変異は、ライフサイクルロジックオプションも提供します.Axiosのスタイルに似ています
    useMutation(addTodo, {
       onMutate: variables => {
         // ... //
         return { id: 1 }
       },
       onError: (error, variables, context) => {
         // ... //
         console.log(`rolling back optimistic update with id ${context.id}`)
       },
       onSuccess: (data, variables, context) => {
         // ... //
       },
       onSettled: (data, error, variables, context) => {
         // ... //
       },
     })
    特にonMutateでは,論理が最初から実行される.これは、「いいね」などのOptimical updateを適用する場合に便利です.

    Invalidation


    invanitionは、一部のクエリが古い状態または開発者が必要とする特殊な状態にある場合にqueryを処理(無効)するために使用されます.通常、変異が発生すると、既存のデータは時代遅れになる可能性が高いため、変異のonSuccessオプションとともに使用されます.
    import { useMutation, useQueryClient } from 'react-query'
     
    const queryClient = useQueryClient()
     
    const mutation = useMutation(addTodo, {
      onSuccess: () => {
        queryClient.invalidateQueries('todos')
        queryClient.invalidateQueries('reminders')
      },
    })
    このプロシージャを使用すると、特定のクエリーは時代遅れになり、現在表示されているクエリーはバックグラウンドで再構築され、最新のデータが保持されます.

    Devtools


    react-queryはブラウザツールを提供します.
    import { ReactQueryDevtools } from 'react-query/devtools'
     
    function App() {
      return (
        <QueryClientProvider client={queryClient}>
          {/* The rest of your application */}
          <ReactQueryDevtools initialIsOpen={false} />
        </QueryClientProvider>
      )
    }
    これらの機能は、keyごとのqueryのリアルタイムステータス情報などのデバッグに役立ちます.
    これは簡単な正式なドキュメントの例です.
    https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/simple

    メリット

  • 非同期論理は非常に簡潔になった.つまり、読みやすさが本当に良くなったということです.
  • クライアントはクライアントの状態のみを保持し、構造はより軽い.
  • ユーザーInfiniteQuery、SSR、GraphQL応答などの強力な機能を提供します.
  • 不便な点

  • 事実上react-queryやswrなどのコンセプトライブラリは使用されたばかりで、まだ大規模なプロジェクトに適用されていないので、まだありません.简洁なハーモニーが心地よかった.
  • saga特定機能の利便性による不便(ex.takeLatest)
  • コンポーネントでqueryを分散するのは不便なので、それを一つの場所に置いて使用し、少し改善しました.
  • // /feedQuery
    
    import { useQuery } from "react-query";
    import { fetchComments } from "../api/fetchComments";
    import { fetchFeeds } from "../api/fetchFeeds";
    
    export const useFetchFeeds = (category, page) =>
      useQuery(category, () => fetchFeeds(category, page));
    
    export const useFetchComments = (id) =>
      useQuery(["comments", id], () => fetchComments(id));
    react-query正式ドキュメント
    https://react-query.tanstack.com/overview