ページャー
ページ自体の表示のほかに、ページ送り、ページの省略表示といったことを考える必要があります。
考え方
- 基本は、総ページ数分のページ番号を表示する。
- ただしページ数が多い場合は、最初、最後、現在のページとその隣のページ以外については「…」で省略する
- 「前へ」「次へ」を表示して、現在のページを増減させた値でイベントを発生させる
// 現在のページの両隣に表示するページ数
const PAGER_NEIGHBORS = 2;
type Props = {
currentPage: number;
totalPages: number;
handlePageChange: (_page: number) => void;
}
const PageList = ({
currentPage,
totalPages,
handlePageChange,
}: Props) => {
const pages = [];
for (let i = 1; i <= totalPages; i++) {
// 2ページ目と最後のページの手前に「...」を差し込む
if (
(i === 2 && currentPage > PAGER_NEIGHBORS + 2) ||
(i === totalPages && currentPage < totalPages - (PAGER_NEIGHBORS + 1))
) {
pages.push(
<li className="ellipse">...</li>
)
}
// ページ番号を表示(最初のページ、最後のページ、現在のページから両隣の定数分表示する)
if (i === 1 || i === totalPage || Math.abs(currentPage + 1) <= PAGER_NEIGHBORS) {
pages.push(
<li
className={`page ${i === currentPage && 'current'}`}
onClick={() => handlePageChange(i)}
>
{i}
</li>
)
}
}
return (
<ul>
<li
className="pager previous"
onClick={() => handlePageChange(
currentPage > 1 ? currentPage - 1 : 1
)}
>前へ</li>
{pages}
<li
className="pager next"
onClick={() => handlePageChange(
currentPage < totalPages ? currentPage + 1 : totalPages
)}
>次へ</li>
</ul>
)
}
地味だが、前後◯ページとの比較をするために、Math.absを使っているところが工夫ポイント(比較演算子の数が減る)。
モーダル
考え方
- ウィンドウ全体を覆う半透明な背景を用意する。
- その上の中心にモーダルを実装する。
- モーダル以外をクリックしたら閉じる(isCancelableがtrueの場合)
type Props = {
isOpen: boolean;
children: React.ReactNode;
handleClose: () => void;
isCancelable: boolean;
}
const Modal = ({
isOpen,
children,
handleClose,
isCancelable,
}: Props) => {
return (
<>
{isOpen && (
<div
className="wrapper"
onClick={() => {
isCancelable && handleClose();
}}
>
<div className="modal">
{children}
</div>
</div>
)}
</>
)
}