KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

react-paginateでページの上下に表示する方法

ページに商品をたくさん並べるときにreact-paginateを使っていたが、上下のページ番号が連動しなかった。

import React, { useState } from "react";
import ReactPaginate from "react-paginate";
import Amazons from "../components/amazons";

const Paginate = ({ itemsPerPage, items }) => {
  /* =====================
   * state
   * ===================== */
  const [itemOffset, setItemOffset] = useState(0);

  /* =====================
   * pagination calculation
   * ===================== */
  const endOffset = itemOffset + itemsPerPage;
  const currentItems = items.slice(itemOffset, endOffset);
  const pageCount = Math.ceil(items.length / itemsPerPage);

  /* =====================
   * handlers
   * ===================== */
  const handlePageClick = (event) => {
    const newOffset =
      (event.selected * itemsPerPage) % items.length;

    setItemOffset(newOffset);
  };

  /* =====================
   * pagination component
   * ===================== */
  const pagination = (
    <ReactPaginate
      breakLabel="..."
      previousLabel="<前へ"
      nextLabel="次へ>"
      pageCount={pageCount}
      pageRangeDisplayed={3}
      onPageChange={handlePageClick}
      renderOnZeroPageCount={null}
      containerClassName="pagination"
      subContainerClassName="pages pagination"
      activeClassName="active"
    />
  );

  /* =====================
   * render
   * ===================== */
  return (
    <>
      {/* 上部ページネーション */}
      {pagination}

      {/* 商品一覧 */}
      <Amazons book={currentItems} />

      {/* 下部ページネーション */}
      {pagination}
    </>
  );
};

export default Paginate;

You:

上下のページネーションの連動させて、できるだけ維持したまま

ChatGPT:

了解です。
「今の構造・見た目・書き方をできるだけ維持したまま、上下のページネーションだけを確実に連動させる」 ですね。

やることは 1点だけ です。


核心(これだけで連動する)

currentPage を state で持ち、forcePage を使う

今は

  • itemOffset だけを state 管理

  • ReactPaginate は内部 state 任せ

なので、上下が同期しません。


最小変更版(ほぼそのまま)

import React, { useState } from "react";
import ReactPaginate from "react-paginate";
import Amazons from "../components/amazons";

const Paginate = ({ itemsPerPage, items }) => {
  /* =====================
   * state
   * ===================== */
  const [currentPage, setCurrentPage] = useState(0);

  /* =====================
   * pagination calculation
   * ===================== */
  const itemOffset = currentPage * itemsPerPage;
  const endOffset = itemOffset + itemsPerPage;
  const currentItems = items.slice(itemOffset, endOffset);
  const pageCount = Math.ceil(items.length / itemsPerPage);

  /* =====================
   * handlers
   * ===================== */
  const handlePageClick = (event) => {
    setCurrentPage(event.selected);
  };

  /* =====================
   * pagination component
   * ===================== */
  const pagination = (
    <ReactPaginate
      breakLabel="..."
      previousLabel="<前へ"
      nextLabel="次へ>"
      pageCount={pageCount}
      pageRangeDisplayed={3}
      onPageChange={handlePageClick}
      forcePage={currentPage}   {/* ★連動の要 */}
      renderOnZeroPageCount={null}
      containerClassName="pagination"
      subContainerClassName="pages pagination"
      activeClassName="active"
    />
  );

  /* =====================
   * render
   * ===================== */
  return (
    <>
      {/* 上部ページネーション */}
      {pagination}

      {/* 商品一覧 */}
      <Amazons book={currentItems} />

      {/* 下部ページネーション */}
      {pagination}
    </>
  );
};

export default Paginate;

何を変えたか(超最小)

変更 理由
itemOffsetcurrentPage ページ番号を単一管理
handlePageClick offset計算を削除
forcePage={currentPage} 上下同期
JSX構造 そのまま

なぜこれで上下が連動するのか

  • 上の ReactPaginate を押す
    setCurrentPage()
    → state 更新
    上下の forcePage が同時に更新

  • 下を押しても同じ流れ


「できるだけ維持」という条件について

✔ JSX構造は維持
pagination 定数も維持
Amazons の呼び出しも変更なし
✔ 見た目・CSS 影響なし

変更行数は実質 5 行程度 です。


追加でやると便利(任意)

フィルタ変更時に1ページ目へ戻す

useEffect(() => {
  setCurrentPage(0);
}, [items]);

結論

上下のページネーションを連動させる唯一の正解は forcePage
この実装は

  • シンプル

  • 壊れにくい

  • ReactPaginate 推奨

です。

次は
👉 ページ変更時にスクロールトップ
👉 モバイル用ページ数削減

どちらを足しますか?

github.com