iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
自我挑戰組

新手前端與真實世界的開發 feat.React 與他的夥伴系列 第 21

Day-21 專案演練 - 打造表格分頁功能 react-table

  • 分享至 

  • xImage
  •  

Day-21 專案演練 - 打造表格分頁功能 react-table

表格分頁是這個專案使用 react-table 製作的最後一個功能,在安裝功能之於,將整理一下原本的分頁區域 UI,修改樣式或者包裝成一個新的檔案,都可以做看看,要看出分頁效果需要更多的資料,也會在今天一併完成。

加入更多的資料

為了要看出分頁的效果,複製很多的 todos 到 list 裡面,準備處理分頁 :

const [list, setList] =
  useState <
  any >
  (() => [
    { time: "2018-07-22", title: "購物", info: "日用品", checked: false },
    { time: "2022-09-15", title: "鐵人賽", info: "day-10", checked: true },
    { time: "2022-09-25", title: "摺棉被", info: "", checked: false },
    ...{ time: "2022-09-25", title: "摺棉被", info: "", checked: false },
  ]);

安裝表格分頁功能

安裝功能的步驟前幾天已經做了很多次,簡單的在複習一下 :

  1. 引入所需的工具
import {
...
  getPaginationRowModel,
} from "@tanstack/react-table";
  1. 安裝到 useTable
  const table = useReactTable({
    data,
    columns,
    state: {
...
    },
    getPaginationRowModel: getPaginationRowModel(),
...

  });

加入功能近 UI

本來是想說把範例程式碼先整組複製近來,在把關鍵的程式碼放到正確的位置裡面,但是沒有想像中這麼順利。範例程式碼裡面有使用到 <button> 元素 :

<button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
  {">"}
</button>

當我將onClick={() => table.nextPage()}disabled={!table.getCanNextPage()}複製進去我原本的 UI 時,當然就出錯了 :

<span onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
  {" "}
  // span 沒有 disabled 屬性所以會報錯
  <svg
    width="32"
    height="32"
    viewBox="0 0 32 32"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M16.7814 16L13.4814 12.7L14.4241 11.7573L18.6668 16L14.4241 20.2427L13.4814 19.3L16.7814 16Z"
      fill="#2D3748"
    />
  </svg>
</span>

後來覺得這樣改很麻煩,就換個做法,把局部需要修改的程式碼用範例程式碼覆蓋,之後在把樣式寫回去。

...
<div className="flex justify-between py-[20px] max-w-[1280px] mx-auto my-0">
        <div className="flex items-center">
          <span>Show rows per page</span>
          <select
            value={table.getState().pagination.pageSize}
            onChange={(e) => {
              table.setPageSize(Number(e.target.value));
            }}
          >
            {[10, 20, 30, 40, 50].map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                Show {pageSize}
              </option>
            ))}
          </select>
        </div>
        <div className="flex items-center">
          <span>
            {" "}
            {table.getState().pagination.pageIndex + 1} of{" "}
            {table.getPageCount()}
          </span>
          <div className="flex">
            <button
              className="border rounded p-1"
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
            >
              {"<"}
            </button>
            <button
              className="border rounded p-1"
              onClick={() => table.nextPage()}
              disabled={!table.getCanNextPage()}
            >
              {">"}
            </button>
          </div>
        </div>
      </div>
      ...

重新撰寫 UI 樣式

把樣式重新寫上去 :

...
        <div className="flex items-center">
          <span>顯示</span>
          <select
            className="select w-[80px] h-[40px] mx-[4px] 
                  rounded border-[2px] border-[#ccc]"
            value={table.getState().pagination.pageSize}
            onChange={(e) => {
              table.setPageSize(Number(e.target.value));
            }}
          >
            {[10, 20, 30, 40, 50].map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                {pageSize}
              </option>
            ))}
          </select>
          <span>頁</span>
        </div>
        <div className="flex items-center">
          <span>
            共 {table.getState().pagination.pageIndex + 1}頁 第{" "}
            {table.getPageCount()} 頁
          </span>
          <div className="flex">
            <button
              className="p-1 mx-[2px]"
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
            >
              {"<"}
            </button>
            <button
              className="p-1 mx-[2px]"
              onClick={() => table.nextPage()}
              disabled={!table.getCanNextPage()}
            >
              {">"}
            </button>
          </div>
        </div>
...

新增 PageCharging

將換頁工具變成一個檔案,放在 features2 :

PageCharging.tsx

import React from "react";

type Props = {
  table;
};

const PageChanging: React.FC<Props> = ({ table }) => {
  return (
    <div className="flex items-center">
      <span>顯示</span>
      <select
        className="select w-[80px] h-[40px] mx-[4px] 
                  rounded border-[2px] border-[#ccc]"
        value={table.getState().pagination.pageSize}
        onChange={(e) => {
          table.setPageSize(Number(e.target.value));
        }}
      >
        {[10, 20, 30, 40, 50].map((pageSize) => (
          <option key={pageSize} value={pageSize}>
            {pageSize}
          </option>
        ))}
      </select>
      <span>頁</span>
    </div>
  );
};

export default PageChanging;

新增 Pagination

跟上一個步驟一樣,新增 Pagination :

import React from "react";

type Props = {
  table;
};

const Pagination: React.FC<Props> = ({ table }) => {
  return (
    <div className="flex items-center">
      <span>
        共 {table.getState().pagination.pageIndex + 1}頁 第{" "}
        {table.getPageCount()} 頁
      </span>
      <div className="flex">
        <button
          className="p-1 mx-[2px]"
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
        >
          {"<"}
        </button>
        <button
          className="p-1 mx-[2px]"
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
        >
          {">"}
        </button>
      </div>
    </div>
  );
};

export default Pagination;

repo

附上程式碼

結語

今天我們完成了表格最後一個功能 :分頁工具。

在初期想得越清楚後期要做的修改就越少,理論是這樣,不過在時間限制之下,很難做到完美,至少要求自己不要做到大改,像今天這樣的 UI 修改,在我自己的界內,在一步一步安裝功能中慢慢地加入細節,我認為這個工作是很迷人的。


上一篇
Day-20 專案演練 - 輸出報表 react-csv
下一篇
Day-22 專案演練 - 修改與刪除代辦清單
系列文
新手前端與真實世界的開發 feat.React 與他的夥伴30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言