Reactコンポーネントの実装カタログ
Reactフロントエンド開発の素養を深めるため、車輪の再発明ではあるが、フロントでよく使われるコンポーネントの実装を行います。
ページャー
ページ自体の表示のほかに、ページ送り、ページの省略表示といったことを考える必要があります。
考え方
- 基本は、総ページ数分のページ番号を表示する。
- ただしページ数が多い場合は、最初、最後、現在のページとその隣のページ以外については「…」で省略する
- 「前へ」「次へ」を表示して、現在のページを増減させた値でイベントを発生させる
1// 現在のページの両隣に表示するページ数
2const PAGER_NEIGHBORS = 2;
3
4type Props = {
5 currentPage: number;
6 totalPages: number;
7 handlePageChange: (_page: number) => void;
8}
9
10const PageList = ({
11 currentPage,
12 totalPages,
13 handlePageChange,
14}: Props) => {
15 const pages = [];
16 for (let i = 1; i <= totalPages; i++) {
17 // 2ページ目と最後のページの手前に「...」を差し込む
18 if (
19 (i === 2 && currentPage > PAGER_NEIGHBORS + 2) ||
20 (i === totalPages && currentPage < totalPages - (PAGER_NEIGHBORS + 1))
21 ) {
22 pages.push(
23 <li className="ellipse">...</li>
24 )
25 }
26 // ページ番号を表示(最初のページ、最後のページ、現在のページから両隣の定数分表示する)
27 if (i === 1 || i === totalPage || Math.abs(currentPage + 1) <= PAGER_NEIGHBORS) {
28 pages.push(
29 <li
30 className={`page ${i === currentPage && 'current'}`}
31 onClick={() => handlePageChange(i)}
32 >
33 {i}
34 </li>
35 )
36 }
37 }
38 return (
39 <ul>
40 <li
41 className="pager previous"
42 onClick={() => handlePageChange(
43 currentPage > 1 ? currentPage - 1 : 1
44 )}
45 >前へ</li>
46 {pages}
47 <li
48 className="pager next"
49 onClick={() => handlePageChange(
50 currentPage < totalPages ? currentPage + 1 : totalPages
51 )}
52 >次へ</li>
53 </ul>
54 )
55}
地味だが、前後◯ページとの比較をするために、Math.absを使っているところが工夫ポイント(比較演算子の数が減る)。
モーダル
考え方
- ウィンドウ全体を覆う半透明な背景を用意する。
- その上の中心にモーダルを実装する。
- モーダル以外をクリックしたら閉じる(isCancelableがtrueの場合)
1type Props = {
2 isOpen: boolean;
3 children: React.ReactNode;
4 handleClose: () => void;
5 isCancelable: boolean;
6}
7
8
9const Modal = ({
10 isOpen,
11 children,
12 handleClose,
13 isCancelable,
14}: Props) => {
15 return (
16 <>
17 {isOpen && (
18 <div
19 className="wrapper"
20 onClick={() => {
21 isCancelable && handleClose();
22 }}
23 >
24 <div className="modal">
25 {children}
26 </div>
27 </div>
28 )}
29 </>
30 )
31}