無限スクロールは、ユーザーがページの末尾に到達すると自動的に次のコンテンツを読み込み、表示することで、途切れることなくコンテンツの探索を可能するものです。ここでは、下方向への無限スクロールをReactで実装します。
実行環境
- wsl2 ubuntu22.04
- npm==9.5.1
- node==v18.16.0
セットアップ
以下のコマンドを実行して、プロジェクトをセットアップします。
mkdir infinite-scroll-react
cd infinite-scroll-react
npx create-react-app --template typescript .
起動
以下のコマンドでサーバーを起動します。通常、localhost:3000でブラウザが起動します。
npm start
必要なライブラリのインストール
別のターミナルを立ち上げ、必要なライブラリをインストールします。また、typescript で実装するため、`@types/react-infinite-scroller`をインストールします。
npm i --save axios react-infinite-scroller
npm i --save-dev @types/react-infinite-scroller
実装
App.tsx を以下のように修正します。このコードはユーザーがページの下に達するたびに新しいデータを自動的に読み込み、表示する処理を行います。
先ほどインストールした react-infinite-scroller ライブラリと axios を使用します。
https://jsonplaceholder.typicode.com/
からダミーデータを取得し、データが読み込まれるたびに既存のリストに追加します。
import InfiniteScroll from "react-infinite-scroller";
import axios from "axios";
import { useState } from "react";
interface ItemState {
userId: number;
id: number;
title: string;
body: string;
}
function App() {
const [items, setItems] = useState<ItemState[]>([]);
const [page, setPage] = useState(1);
const fetchData = async () => {
const response = await axios.get(
`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
);
setItems([...items, ...response.data]);
setPage(page + 1);
};
return (
<InfiniteScroll
style={{ margin: "10px" }}
pageStart={0}
loadMore={fetchData}
hasMore={true}
loader={
<div className="loader" key={0}>
Loading ...
</div>
}
>
{items.map((item) => (
<div key={item.id}>
<h2>{item.title}</h2>
<p>{item.body}</p>
</div>
))}
</InfiniteScroll>
);
}
export default App;
InfiniteScroll コンポーネントの細かな設定は 以下の通りです。詳細については Github を確認してください。
名称 | 必須 | 型 | デフォルト値 | 説明 |
---|---|---|---|---|
children | はい | Node | レンダリング可能なもの(PropTypeのNodeと同じ) | |
loadMore | はい | 関数 | ユーザーが更にアイテムを要求した時に呼び出されるコールバック関数。ページを指定する単一のパラメータを受け取ります。例:function handleLoadMore(page) { /* ここで更にアイテムを読み込む */ } |
|
element | いいえ | コンポーネント | ‘div’ | コンポーネントがレンダリングすべき要素の名前 |
hasMore | いいえ | Boolean | false | 更に読み込むべきアイテムがあるかどうか。falseの場合、イベントリスナーは削除されます。 |
initialLoad | いいえ | Boolean | true | コンポーネントが最初のアイテムセットを読み込むべきかどうか |
isReverse | いいえ | Boolean | false | スクロール可能エリアの上部にユーザーがスクロールした時に新しいアイテムを読み込むべきかどうか |
loader | いいえ | コンポーネント | 更にアイテムを読み込んでいる間にレンダリングするReactコンポーネント。親コンポーネントはユニークなkeyプロパティを持つ必要があります。 | |
pageStart | いいえ | 数値 | 0 | 読み込む最初のページの番号。デフォルトの0では、最初のページは1です。 |
getScrollParent | いいえ | 関数 | 無限スクロールのコンポーネントの直接の親でない別のスクロールリスナーを返すメソッドをオーバーライドする場合に使用します。 | |
threshold | いいえ | 数値 | 250 | アイテムの終わりから、loadMoreを呼び出すトリガーとなる距離(ピクセル単位)。 |
useCapture | いいえ | Boolean | false | 追加されたイベントリスナーのuseCaptureオプションへのプロキシ |
useWindow | いいえ | Boolean | true | スクロールリスナーをウィンドウに追加するか、それとも、コンポーネントのparentNodeに追加するか |
まとめ
react-infinite-scroller
ライブラリを用いた無限スクロールの実装方法について紹介しました。無限スクロールに関しては他にも様々な方法で実現できます。