NU:LOGiC Logo

【React.js + useSWR】SWR Infiniteを使ったページネーション・無限スクロールの実装方法を解説!

【React.js + useSWR】SWR Infiniteを使ったページネーション・無限スクロールの実装方法を解説!

SWRは、Next.jsの開発元でもあるVercelが開発したReact向けのデータ取得ライブラリです。SWRは、アプリケーションのパフォーマンスを向上させ、データの取得と更新を簡単に行えるように設計されています。

ローカル上のキャッシュとサーバーとの間でデータを自動的に管理することで、適切なタイミングでキャッシュを更新します。また、オプションを設定することで、キャッシュの有効期限や再取得のタイミングを調整することができます。

今回は、そのSWRのうちページネーションを可能にするuseSWRInfiniteについて解説します!

3行で要約すると

  • SWRは、効率的なデータ取得とユーザー体験の向上を目指して設計されている。
  • useSWRInfiniteはSWRライブラリのフックで、ページネーションや無限スクロールを簡単に実装できる。
  • ボタンクリックやスクロールイベントを利用して、次のページのデータを動的に読み込む方法を提供する。

useSWRInfiniteとは?

useSWRInfiniteは、ページネーションや無限ローディングを実現するためのReactフックです。このフックを使用することで、ユーザーがスクロールするたびに新しいコンテンツを動的に読み込むことができます。これにより、従来のページネーションのように、ページ番号をクリックして新しいページを読み込む必要がなくなります。

useSWRInfiniteを使用することで、これらの問題を簡単に解決し、効果的な無限ローディングの実装を行うことができます。

セットアップ

useSWRInfiniteを使用するためのセットアップは非常に簡単です。まず、必要なライブラリをインストールします。

npm install swr

次に、あなたのReactコンポーネントでuseSWRInfiniteをインポートします。

import useSWRInfinite from 'swr'

これで、useSWRInfiniteを使用してページネーションや無限ローディングを実装する準備が整いました。このフックは、APIエンドポイントやデータの取得方法を指定することで、必要なデータを動的に取得することができます。

例えば、以下のコードは、/api/dataエンドポイントからデータを取得し、ページネーションを実装する方法を示しています。

const { data, error, size, setSize } = useSWRInfinite(
  (index) => `/api/data?page=${index + 1}`,
  fetcher
);

ここで、indexは現在のページ番号を示し、fetcherはデータを取得するための関数です。sizeは現在のページ数を示し、setSizeはページ数を更新するための関数です。

このように、useSWRInfiniteを使用することで、簡単にページネーションや無限ローディングの機能を追加することができます。

了解しました。

useSWRInfiniteの基本的な使い方

useSWRInfiniteを使用してデータのページネーションを実装する基本的な方法を以下に示します。

まず、必要な関数とフックをインポートします。

import useSWRInfinite from 'swr';

次に、getKey関数とfetcher関数を定義します。

const getKey = (pageIndex, previousPageData) => {
  if (previousPageData && !previousPageData.length) return null; // reached the end
  return `/api/data?page=${pageIndex + 1}`;
}

const fetcher = url => fetch(url).then(res => res.json());

これで、useSWRInfiniteフックを使用してデータを取得することができます。

function MyComponent() {
  const { data, error, size, setSize } = useSWRInfinite(getKey, fetcher);

  if (error) return <div>Error loading data</div>;
  if (!data) return <div>Loading...</div>;

  return (
    <div>
      {data.map((pageData, index) => (
        <div key={index}>
          {pageData.map(item => (
            <div key={item.id}>{item.name}</div>
          ))}
        </div>
      ))}
      <button onClick={() => setSize(size + 1)}>Load more</button>
    </div>
  );
}

上記のコードでは、useSWRInfiniteを使用して複数ページのデータを取得し、それを表示しています。また、"Load more"ボタンをクリックすることで、次のページのデータを読み込むことができます。

引数

getKey この関数は、ページのインデックスや他の情報を受け取り、APIエンドポイントのURLを返します。

const getKey = (pageIndex, previousPageData) => {
  if (previousPageData && !previousPageData.length) return null; // reached the end
  return `/api/data?page=${pageIndex + 1}`;
}

fetcher APIエンドポイントからデータを取得するための関数です。通常、fetchaxiosなどのHTTPクライアントを使用して実装されます。

const fetcher = url => fetch(url).then(res => res.json());

返り値

data フェッチされたデータの配列。各ページのデータを含む配列の配列として返されます。

const { data } = useSWRInfinite(getKey, fetcher);

error データの取得中にエラーが発生した場合に返されるエラーオブジェクト。

const { error } = useSWRInfinite(getKey, fetcher);
if (error) console.error("Error fetching data:", error);

size 現在のページ数を示す数値。

const { size } = useSWRInfinite(getKey, fetcher);
console.log("Current page size:", size);

setSize ページ数を更新するための関数。次のページのデータを取得するために使用します。

const { setSize } = useSWRInfinite(getKey, fetcher);
const loadMore = () => setSize(size + 1);

isValidating データの再検証が行われているかどうかを示すブール値。

const { isValidating } = useSWRInfinite(getKey, fetcher);
if (isValidating) console.log("Data is revalidating");

mutate データを手動で再検証するための関数。

const { mutate } = useSWRInfinite(getKey, fetcher);
const refreshData = () => mutate();

これらの引数と返り値を組み合わせることで、ページネーションや無限スクロールのロジックを簡単に実装することができます。

ボタンを押して次のページを読み取る実装

useSWRInfiniteを使用して、ボタンをクリックすることで次のページのデータを読み込む方法を以下に示します。

まず、useSWRInfiniteフックを使用してデータを取得します。

const { data, size, setSize } = useSWRInfinite(getKey, fetcher);

次に、"次のページを読み込む"ボタンを実装します。このボタンは、クリックされるとsetSize関数を使用してページ数を増やし、次のページのデータを読み込みます。

<button onClick={() => setSize(size + 1)}>次のページを読み込む</button>

このボタンのクリックイベントは、現在のページ数(size)に1を加えて、setSize関数を呼び出すことで次のページのデータを取得します。

また、すべてのデータが読み込まれた場合やエラーが発生した場合には、ボタンを非活性にするなどの処理を追加することができます。

無限スクロールの実装

無限スクロールは、ユーザーがページの最後までスクロールすると自動的に次のページのデータを読み込む機能を指します。useSWRInfiniteを使用することで、この機能を簡単に実装することができます。

まず、useSWRInfiniteフックと必要な関数をセットアップします。

const { data, size, setSize } = useSWRInfinite(getKey, fetcher);

次に、スクロールイベントを監視して、ユーザーがページの最後までスクロールしたかどうかを判断します。これを実現するために、windowオブジェクトのscrollイベントを使用します。

useEffect(() => {
  const handleScroll = () => {
    if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
      setSize(size + 1);
    }
  };

  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, [size, setSize]);

これらのシンプルな実装を使用して、ユーザーがボタンをクリックすることで次のページのデータを動的に読み込む機能を追加することができます。

まとめ

今回の記事では、useSWRInfiniteの基本的な使い方から、ボタンをクリックして次のページを読み込む方法、無限スクロールの実装方法までを詳しく解説しました。これらの知識を活用することで、ユーザー体験を向上させるデータ取得のロジックを簡単に実装することができます。