【React】ページネーションを自作する方法

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関数を発火させれば完成です。

React

Posted by devsakaso