技術ブログ

プログラミング、IT関連の記事中心

React(TypeScript)でライブラリを使用せずに、ソートとページャーがついたテーブルを実装する方法(table、sort、pager)

目次

完成したテーブル

本記事のコンポーネントでは、以下の画像のテーブルが作成できます。

テーブルのコンポーネント作成

以下、「CustomTable」という名前でコンポーネントを用意します。

import React, { useEffect } from "react";

const CustomTable = ({ header = [], body = [], pageLen = 5 }: Props) => {
  const [bodyData, setBodyData] = React.useState(body); // 画面描画データ
  const [pagerList, setPagerList] = React.useState<number[]>([]); // ページ表示情報
  const [pageNum, setPageNum] = React.useState(1); // ページ番号

  // =====ページャー=====

  const changePage = (num: number) => {
    setPageNum(num);
    pageChangeList(num);
  };

  const pageChangeList = (num: number) => {
    const pageMax = Math.ceil(bodyData.length / pageLen);
    let pager = [];
    if (pageMax > 5) {
      if (num < 3) {
        for (let r = 1; r <= 5; r++) {
          pager.push(r);
        }
      } else if (num > pageMax - 2) {
        const lowNum = pageMax - 5;
        for (let r = lowNum; r <= pageMax; r++) {
          pager.push(r);
        }
      } else {
        const lowNum = num - 2;
        const heiNum = num + 2;
        for (let r = lowNum; r <= heiNum; r++) {
          pager.push(r);
        }
      }
    } else {
      for (let r = 1; r <= pageMax; r++) {
        pager.push(r);
      }
    }
    setPagerList(pager);
  };

  // =====ソート=====
  const [columnNo, setColumnNo] = React.useState(-1); // 前回クリックされた列番号

  // 配列のソート
  const arraySortAct = (a: any, b: any) => {
    if (!isNaN(a) && !isNaN(b)) {
      return a - b;
    } else {
      if (a > b) {
        return -1;
      } else {
        return 1;
      }
    }
  };

  // ソートの処理
  const sortAct = (e: any) => {
    var target = e.srcElement || e.target;
    const nowClm = target.cellIndex;
    const targett = bodyData.concat();

    if (columnNo === nowClm) {
      // 昇順
      targett.sort((a, b) => arraySortAct(a[nowClm], b[nowClm]));
      setBodyData(targett);
      setColumnNo(-1);
    } else {
      // 降順
      targett.sort((a, b) => arraySortAct(b[nowClm], a[nowClm]));
      setBodyData(targett);
      setColumnNo(nowClm);
    }
  };

  useEffect(() => {
    const pageMax = Math.ceil(bodyData.length / pageLen);
    let pager = [];
    if (pageMax > 5) {
      for (let r = 1; r <= 5; r++) {
        pager.push(r);
      }
    } else {
      for (let r = 1; r <= pageMax; r++) {
        pager.push(r);
      }
    }
    setPagerList(pager);
  }, []);

  return (
    <div>
      <table id="sort_table">
        <tr>
          {header.map((tgt) => (
            <th onClick={sortAct}>{tgt}</th>
          ))}
        </tr>
        {bodyData.map((tgt, index) => {
          const minPage = (pageNum - 1) * pageLen;
          const maxPage = minPage + pageLen;
          if (index >= minPage && index < maxPage) {
            return (
              <tr>
                {tgt.map((data) => (
                  <td
                    onClick={() => {
                      console.log("========HELLO");
                      console.log(`行数:${index}`);
                      console.log(`行データ:${tgt}`);
                    }}
                  >
                    {data}
                  </td>
                ))}
              </tr>
            );
          } else {
            return <></>;
          }
        })}
      </table>
      <button
        onClick={() => {
          if (pageNum > 1) {
            changePage(pageNum - 1);
          }
        }}
      >
        前へ
      </button>
      {pagerList.map((val) => (
        <button onClick={() => changePage(val)}>{val}</button>
      ))}
      <button
        onClick={() => {
          const pageMax = Math.ceil(bodyData.length / pageLen);
          if (pageNum < pageMax) {
            changePage(pageNum + 1);
          }
        }}
      >
        次へ
      </button>
    </div>
  );
};

type Props = {
  header?: string[]; // テーブルヘッダー
  body?: Array<string[]>; // テーブル表示データ
  pageLen?: number; // 1ページの上限件数
};

export default CustomTable;

テーブルコンポーネントを使用

以下の様に「PageData」というページにコンポーネントを呼び出して使用する事で、カスタムテーブルが表示されます。

import CustomTable from "./CustomTable";

const PageData = () => {
  return (
    <div>
      <CustomTable
        header={["No", "あああ", "いいい", "ううう"]}
        body={[
          ["1", "あasds", "か", "123"],
          ["2", "あi,1", "か", "123"],
          ["3", "あ3,u", "か", "123"],
          ["4", "あasd", "か", "123"],
          ["5", "あnt1", "か", "123"],
          ["6", "あdd3", "か", "123"],
          ["7", "あcasc", "か", "123"],
          ["8", "あs1", "か", "123"],
          ["9", "あ ad3", "か", "123"],
          ["10", "あas", "か", "123"],
          ["11", "あdht1", "か", "123"],
          ["12", "あi,3", "か", "123"],
          ["1", "あasds", "か", "123"],
          ["2", "あi,1", "か", "123"],
          ["3", "あ3,u", "か", "123"],
          ["4", "あasd", "か", "123"],
          ["5", "あnt1", "か", "123"],
          ["6", "あdd3", "か", "123"],
          ["7", "あcasc", "か", "123"],
          ["8", "あs1", "か", "123"],
          ["9", "あ ad3", "か", "123"],
          ["10", "あas", "か", "123"],
          ["11", "あdht1", "か", "123"],
          ["12", "あi,3", "か", "123"],
          ["6", "あdd3", "か", "123"],
          ["7", "あcasc", "か", "123"],
          ["8", "あs1", "か", "123"],
          ["9", "あ ad3", "か", "123"],
          ["10", "あas", "か", "123"],
          ["11", "あdht1", "か", "123"],
          ["12", "あi,3", "か", "123"],
        ]}
      />
    </div>
  );
};

export default PageData;

ソートの方法

完成したテーブルのヘッダーをクリックすることで、ソートが実行されます。

1度クリックすると、「降順」
もう一度同じヘッダーをクリックすると、「昇順」になります。

フィルターの方法

テーブルの下の数字のボタンが、ページ数になります。
ボタンを押下することで、該当のページに切り替わります。

「前へ」ボタンは、1つ前のページへ切り替わります。
※現在のページが1ページ目だと動作しません。

「次へ」ボタンは、1つ次のページへ切り替わります。
※現在のページが最後のページだと動作しません。