4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

material-uiのTable sortの例がわかりづらかったので整理

Posted at

はじめに

material-uiでテーブルをソートしたかったのですが、
例を見たときにcheckboxやページ切り替えが混ざりコードが多すぎたので整理しました

今回はmaterial-uiのBasic tableをもとにソートだけを実装しています

必要そうな処理

  • ソート方法の保持処理
  • ソート対象の保持処理
  • ソート対象、方法の変更処理
  • ソート実行処理
  • 比較処理
  • JSXの修正
    • TableSortLabelの追加
    • TableHeadのTableCellにsortDirection追加
    • TableBodyのTableCellをソート順に表示

※見やすいようにTableHeadのTableCellも表示方法も修正しています

変更後のコード

import {useState} from "react";
import TableSortLabel from "@mui/material/TableSortLabel";

import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";



function createData(name: string, calories: number, fat: number, carbs: number, protein: number) {
  return { name, calories, fat, carbs, protein };
}

const rows = [
  createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
  createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
  createData("Eclair", 262, 16.0, 24, 6.0),
  createData("Cupcake", 305, 3.7, 67, 4.3),
  createData("Gingerbread", 356, 16.0, 49, 3.9),
];

function createColumn(
  id: string,
  label: string,
  align: "left" | "right" | "center" | "inherit" | "justify" | undefined
) {
  return { id, label, align };
}

const columns = [
  createColumn("name", "Dessert (100g serving)", "left"),
  createColumn("calories", "Calories", "right"),
  createColumn("fat", "Fat (g)", "right"),
  createColumn("carbs", "Carbs (g)", "right"),
  createColumn("protein", "Protein (g)", "right"),
];


export default function BasicTable() {

  //ソート方法
  const [order, setOrder] = useState<"desc" | "asc">("desc");
  //ソート対象
  const [orderBy, setOrderBy] = useState<string>("calories");

  //ソート対象、方法の変更
  const handleRequestSort = (event:any, property:any) => {
    const isAsc = orderBy === property && order === "asc";
    setOrder(isAsc ? "desc" : "asc");
    setOrderBy(property);
  };
  const createSortHandler = (property:any) => (event:any) => {
    handleRequestSort(event, property);
  };

  //ソート実行
  function stableSort(array:any, comparator:any) {
    const stabilizedThis = array.map((el:any, index:any) => [el, index]);
    stabilizedThis.sort((a:any, b:any) => {
      const order = comparator(a[0], b[0]);
      if (order !== 0) {
        return order;
      }
      return a[1] - b[1];
    });
    return stabilizedThis.map((el:any) => el[0]);
  }

  //比較処理
  function descendingComparator(a:any, b:any, orderBy:any) {
    if (b[orderBy] < a[orderBy]) {
      return -1;
    }
    if (b[orderBy] > a[orderBy]) {
      return 1;
    }
    return 0;
  }
  function getComparator(order:any, orderBy:any) {
    return order === "desc" 
      ? (a:any, b:any) => descendingComparator(a, b, orderBy)
      : (a:any, b:any) => -descendingComparator(a, b, orderBy);
  }

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            {columns.map((column) => (
              <TableCell align={column.align} sortDirection={orderBy === column.id ? order : 'desc'}>
                {column.label}
                <TableSortLabel
                  active={orderBy === column.id}
                  direction={orderBy === column.id ? order : "asc"}
                  onClick={createSortHandler(column.id)}
                ></TableSortLabel>
              </TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {stableSort(rows, getComparator(order, orderBy)).map((row:any) => (
            <TableRow key={row.name} sx={{ "&:last-child td, &:last-child th": { border: 0 } }}>
              <TableCell component="th" scope="row">
                {row.name}
              </TableCell>
              <TableCell align="right">{row.calories}</TableCell>
              <TableCell align="right">{row.fat}</TableCell>
              <TableCell align="right">{row.carbs}</TableCell>
              <TableCell align="right">{row.protein}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}


注意として、ソートはcolumnsのidを元にソート対象を判断しているため、
rowsのキーとcolumnsのidは同じにします

終わり

Reactを勉強し始めたばっかりなので、間違いあれば教えてください

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?