GatsbyJSで作ったサイト日本の一覧を表示すると数が多いとページャーで分割して表示する。
Gatsbyとページャーで検索すると「Adding Pagination」で追加する方法があるが、別のページが生成されるので目的とは違った。
そこで、ReactPaginateを使って画面に表示する内容を切り替える。
渡すデータは次の形式のjson。実際のデータは10個以上の大きさを渡している。データの取得はPA-APIを利用している。
実際の表示
[
{
"Asin": "B0CPPC5RKF",
"URL": "https://www.amazon.co.jp/dp/B0CPPC5RKF?tag=99hatena-22&linkCode=ogi&th=1&psc=1",
"ImageURL": "https://m.media-amazon.com/images/I/51lVHGs0ZDL._SL500_.jpg",
"Publisher": "KADOKAWA",
"Contributor": "脇岡こなつ(著)",
"Booktype": "Kindle版",
"Title": "なぜかS級美女達の話題に俺があがる件2【電子特別版】 (角川スニーカー文庫)",
"Price": 616,
"Category": "ライトノベル,ライトノベル,日本の小説・文芸",
"Points": 6
},
{
"Asin": "B0C5L6KT9F",
"URL": "https://www.amazon.co.jp/dp/B0C5L6KT9F?tag=99hatena-22&linkCode=ogi&th=1&psc=1",
"ImageURL": "https://m.media-amazon.com/images/I/51qz+212n7L._SL500_.jpg",
"Publisher": "KADOKAWA",
"Contributor": "脇岡こなつ(著)",
"Booktype": "Kindle版",
"Title": "なぜかS級美女達の話題に俺があがる件 (角川スニーカー文庫)",
"Price": 581,
"Category": "ライトノベル,ライトノベル,日本の小説・文芸",
"Points": 6
},
{
"Asin": "B0CVRCWBKL",
"URL": "https://www.amazon.co.jp/dp/B0CVRCWBKL?tag=99hatena-22&linkCode=ogi&th=1&psc=1",
"ImageURL": "https://m.media-amazon.com/images/I/51b6J-FJmTL._SL500_.jpg",
"Publisher": "KADOKAWA",
"Contributor": "木嶋 隆太(著)",
"Booktype": "Kindle版",
"Title": "妹の迷宮配信を手伝っていた俺が、うっかりSランクモンスター相手に無双した結果がこちらです【電子特別版】 (角川スニーカー文庫)",
"Price": 616,
"Category": "ライトノベル,ライトノベル,日本の小説・文芸",
"Points": 6
},]
Amazonsコンポーネントで受け取って画面に表示する。このコンポーネントをページャーで分割する。
const Amazons = ({ book }) => {
//数の制限
//book.length=20
var image_m
var image_s
for (let i = 0; i < book.length; i++) {
image_m=book[i].ImageURL.replace(/_SL500_/, '_SL160_');
image_s=book[i].ImageURL.replace(/_SL500_/, '_SL75_');
book[i].image_m=image_m;
book[i].image_s=image_s;
}
//重複の削除
//https://qiita.com/allJokin/items/28cd023335641e8796c5
const uniqueUsers = Array.from(new Map(book.map((user) => [user.Asin, user])).values()
);
return (
<div id="book">
{uniqueUsers.map(e => (
<div key={e.Asin}>
<a className="amazon-card-container" target="_blank" rel="noopener noreferrer" href={e.URL}>
<div className="amazon-card-body">
<div className="amazon-card-title">{e.Title}</div>
<div className="amazon-card-domain">価格:{e.Price}円、ポイント:{e.Points}、{e.Contributor}、出版社:{e.Publisher}、カテゴリー:{e.Category}</div>
</div>
<div className="amazon-card-image-container">
<img className="amazon-card-image"
srcSet={`${e.image_s} 320w, ${e.image_m} 640w, ${e.ImageURL} `}
src={e.image_s}
sizes="(max-width:1280px) 50vw, 1280px"
loading="lazy" alt={e.Title}/>
</div>
</a>
</div>
))}
</div>
)
}
react-paginateのusageをもとにAmazonsコンポーネントを利用して表示に書き換えた。上下にページネーションを表示している。
import React, { useState } from 'react';
import ReactPaginate from 'react-paginate';
import Amazons from "../components/amazons"
const Paginate = ({ itemsPerPage,items }) => {
function Items({ currentItems }) {
return (
<>
<Amazons book={currentItems} />
</>
);
}
// Here we use item offsets; we could also use page offsets
// following the API or data you're working with.
const [itemOffset, setItemOffset] = useState(0);
// Simulate fetching items from another resources.
// (This could be items from props; or items loaded in a local state
// from an API endpoint with useEffect and useState)
const endOffset = itemOffset + itemsPerPage;
// console.log(`Loading items from ${itemOffset} to ${endOffset}`);
const currentItems = items.slice(itemOffset, endOffset);
const pageCount = Math.ceil(items.length / itemsPerPage);
// Invoke when user click to request another page.
const handlePageClick = (event) => {
const newOffset = (event.selected * itemsPerPage) % items.length;
console.log(
`User requested page number ${event.selected}, which is offset ${newOffset}`
);
setItemOffset(newOffset);
};
return (
<>
<ReactPaginate
breakLabel="..."
nextLabel="次へ>"
onPageChange={handlePageClick}
pageRangeDisplayed={3}
pageCount={pageCount}
previousLabel="<前へ"
renderOnZeroPageCount={null}
containerClassName={'pagination'} /* as this work same as bootstrap class */
subContainerClassName={'pages pagination'} /* as this work same as bootstrap class */
activeClassName={'active'} /* as this work same as bootstrap class */
/>
<Items currentItems={currentItems} />
<ReactPaginate
breakLabel="..."
nextLabel="次へ>"
onPageChange={handlePageClick}
pageRangeDisplayed={3}
pageCount={pageCount}
previousLabel="<前へ"
renderOnZeroPageCount={null}
containerClassName={'pagination'} /* as this work same as bootstrap class */
subContainerClassName={'pages pagination'} /* as this work same as bootstrap class */
activeClassName={'active'} /* as this work same as bootstrap class */
/>
</>
);
}
export default Paginate
スタイルシートは下記記事を下にクラスを割り当てている。
参考