SSRとページ化を反応質問で結合する方法


あなたが反応質問でPaginationについての私の最新のポストを読むならば、あなたはすべてがクライアント側でレンダリングされたと気がつきました.それはいくつかのケースでは良いですが、他の場合は、より良い速度やSEOのサーバー側のレンダリングを必要とする場合があります.今日は、私たちが前回作成したコードを次のサーバーサイドでレンダリングしたページを設定します.JSと対応するクエリ

プロジェクトの設定


新しいプロジェクトのセットアップであなたを退屈させないために、我々はちょうど前からコードを修正するでしょう.先に行くとクローンrepository : PaginationSSR内で完成したコードを検査できます.ページディレクトリのJSファイルまたはPaginationCSRからコードをコピーします.新しいページの中のJSと一緒に続いてください.

2 .サーバ側のデータを取得する2つの方法の評価


詳細はreact-query docs SSRでは、データをページに渡す方法が2つあります

初期データの使用


これは非常に簡単です:私たちはちょうどサーバ側で必要なデータを取って、質問をinitaldataとして反応させるためにそれを与えます、そして、我々はすべてセットされます.しかし、いくつかの欠点があります.
  • 私たちは、正確にデータがいつ取得されたかを知りません
  • クエリは、この初期値データが正確に何かわからない.最初のページのデータをサーバー側の初期値データとして渡すと、応答クエリはクライアント側で同じデータを取得し、不要なAPIリクエストを追加します.
  • b .水和の利用


    前述の問題は水和を使用して回避されますが、セットアップは少し複雑です.しかしながら、私はあなたに防弾と生産準備がある解決を提供したいので、我々はオプションBとともに行きます.

    水和の設定

  • 最初の変更は、アプリで行われる必要があります.JS :私たちは外部の代わりにアプリの内部QueryClientを作成します.また、追加のハイドレートのコンポーネント内のアプリをラップする必要がありますし、脱水状態でpropとして渡す.結果は次のようになります.
  • import "../styles/globals.css";
    import { ReactQueryDevtools } from "react-query/devtools";
    
    import { Hydrate, QueryClient, QueryClientProvider } from "react-query";
    import { useState } from "react";
    
    function MyApp({ Component, pageProps }) {
      const [queryClient] = useState(() => new QueryClient());
      return (
        <QueryClientProvider client={queryClient}>
          <Hydrate state={pageProps.dehydratedState}>
            <Component {...pageProps} />
            <ReactQueryDevtools initialIsOpen={false}></ReactQueryDevtools>
          </Hydrate>
        </QueryClientProvider>
      );
    }
    
    export default MyApp;
    
  • さて、まだ実行していない場合は、PaginationSSRというページフォルダに新しいファイルを作成します.JPとPaginationCSRの中のすべてのコードをコピーして貼り付けます.jsコンポーネントの名前を変更するだけで、すべてが期待通りに動作していることを確認します.
  • GetServerSideProps関数から始めましょう.新しいQueryClientを定義し、プリフェッチクエリ関数を使用する必要があります.結果は、我々のページに小道具の内部でdehydratedstateとして返されます.ここで書くクエリは、ページコンポーネント内のものと同じ名前と依存関係の配列を持たなければならないことに注意してください.さもなければ、それは既存の問い合わせのプリフェッチとして扱われ、データはガベージコレクションされます.結果のコードは次のようになります.
  • export async function getServerSideProps(context) {
      let page = 1;
      if (context.query.page) {
        page = parseInt(context.query.page);
      }
      const queryClient = new QueryClient();
      await queryClient.prefetchQuery(
        ["characters", page],
        async () =>
          await fetch(
            `https://rickandmortyapi.com/api/character/?page=${page}`
          ).then((result) => result.json()),
      );
      return { props: { dehydratedState: dehydrate(queryClient) }    };
    }
    
  • 我々はほとんど完了です!わずかな調整しか残っていない.一方で、あなたが入力するときに、あなたは反応質問devtoolsで気づくでしょうlocalhost:3001/paginationSSR?page=14 例えば14ページに直接移動するには、ページ1のデータも取得します.これはページのデフォルト値が1に設定されているため、1ページ目のデータを描画直後に取得します.以下のように修正します.
  • const [page, setPage] = useState(parseInt(router.query.page) || 1);
    
    これで、useEffectフックを削除できます.このページはサーバー側でレンダリングされているので、すぐにページパラメータにアクセスできます.
  • 最後に少なくとも最後に、handlePaginationChange関数の中の基本URLを変更することを忘れないでください.サーバー側のレンダリングをテストするとき、物事は非常に混乱してしまいます.🤦🏼‍♀️
  •   function handlePaginationChange(e, value) {
        setPage(value);
        router.push(`paginationSSR/?page=${value}`, undefined, { shallow: true });
      }
    

    追加コメント

  • Reply Queryは、データをやり取りするためのいくつかの非常に攻撃的なデフォルトを持ちます.これが私が設定した理由ですrefetchonMount and refetchOnWindowFocus 嘘をつく.あなたはそれがアクティブにしておくのが最善かどうかあなたのユースケースを評価する必要があります.
  •   const { data } = useQuery(
        ["characters", page],
        async () =>
          await fetch(
            `https://rickandmortyapi.com/api/character/?page=${page}`
          ).then((result) => result.json()),
        {
          keepPreviousData: true,
          refetchOnMount: false,
          refetchOnWindowFocus: false,
        }
      );
    
  • 実際のアプリケーションでは、グリッドと一緒にページネーションコンポーネントを別のコンポーネントにカプセル化して再利用するのが最善でしょう.しかし、常にあなたの将来とあなたの同僚の人生をより簡単にするためにコード再利用性について考える分を取る.❤️
  • 今日はこれです.コメントのセクション内の任意の質問を削除し、素晴らしい週をお過ごしください!