【React】ページネーションを自作する方法
Reactで外部API(JSON)から取得したデータで、次のデータと前のデータを表示するために、ページネーションを自作する方法を紹介します。
今回は、ポケモンAPIで実際に取得して表示します。
Reactでページネーションを自作する方法
ファイル構成
src
∟App.js
∟index.js
∟components
∟Card
∟Card.js
∟utils
get.js
App.jsでループして外部API(JSON)を取得した分だけCardを作成する構成とします。
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
上でAppを読み込みます。
index.jsは特にいじるところはありません。
App.js
import { useEffect, useState } from "react";
import Card from "./components/Card/Card";
function App() {
// 外部API
const initialURL = "https://endpoint"; //endpoint
const [loading, setLoading] = useState(true); //最初にloading出したいのでtrue
const [someData, setSomeData] = useState([]);
const [nextURL, setNextURL] = useState(""); //次の20件のURLの状態
const [prevURL, setPrevURL] = useState(""); //前の20件のURLの状態
useEffect(() => {
const fetchSomeData = async () => {
// すべてのポケモンデータを取得
let res = await getAllSome(initialURL);
// console.log(res);
// console.log(res.next); //次の20件がある
// console.log(res.previous); //前の20件がある
// 詳細データを取得
loadSome(res.results);
setNextURL(res.next);
setPrevURL(res.previous);
setLoading(false);
};
fetchSomeData();
}, []);
const handlePrevPage = async () => {
if(!prevURL) return; //1ページ目は前のデータはないので、returnしておく
setLoading(true);
let data = await getAllSome(prevURL);
await loadSome(data.results);
setNextURL(data.next);
setPrevURL(data.previous);
setLoading(false);
// console.log(data);
};
const handleNextPage = async () => {
if(!nextURL) return;
setLoading(true);
let data = await getAllSome(nextURL);
await loadSome(data.results);
setNextURL(data.next); //3ページ目以降のデータを取得するために状態を変更
setPrevURL(data.previous); //2ページ目以降で前へのデータを取得する
setLoading(false);
// console.log(data);
};
return (
<>
<div className="App">
{loading ? (
<p className="loader">ロード中。。。</p>
) : (
<>
<div>
{someData.map((some, i) => {
return <Card key={i} some={some} />;
})}
</div>
<div className="btn">
<button onClick={handlePrevPage}>前へ</button>
<button onClick={handleNextPage}>次へ</button>
</div>
</>
)}
</div>
</>
);
}
export default App;
外部APIから取得して、Cardコンポーネントをmapを使ってデータを表示しています。
ページネーション部分のみを説明します。
<div className="btn">
<button onClick={handlePrevPage}>前へ</button>
<button onClick={handleNextPage}>次へ</button>
</div>
JSX部分で、ボタンを用意します。
そのボタンにはそれぞれ前のデータを取得するhandlePrevPage関数と次のデータを取得するhandleNextPage関数を設定しています。
const [nextURL, setNextURL] = useState(""); //次の20件のURLの状態
const [prevURL, setPrevURL] = useState(""); //前の20件のURLの状態
前のページと次のページは現在のページで変わるため、状態管理をします。
const handlePrevPage = async () => {
if(!prevURL) return; //1ページ目は前のデータはないので、returnしておく
setLoading(true);
let data = await getAllSome(prevURL);
await loadSome(data.results);
setNextURL(data.next);
setPrevURL(data.previous);
setLoading(false);
// console.log(data);
};
まず、jsonに次のデータと前のデータが格納されているプロパティがあるはずなので、それを探します。上の場合は、data.nextとdata.previousというプロパティがある場合です。
handlePrevPage関数とhandleNextPage関数はほぼ同じなので、handlePrevPage関数だけ説明すると、取得したデータをロードしたら、それぞれの更新用関数に取得した次と前のデータをセットします。
そうすることで、常に現在のページの次と前のデータが保持されます。
あとは、初回ロード時と、前へボタン、次へボタンが押されたタイミングで、handlePrevPage関数とhandleNextPage関数を発火させれば完成です。