본문 바로가기
개발/React

React Material - Mui Table 세로 줄 변경하기 (Enable Column Ordering)

by 피로물든딸기 2023. 7. 12.
반응형

리액트 전체 링크

 

참고

- column ordering

- 로컬 스토리지 사용 방법과 세션 스토리지 비교

- Mui Table 옵션 설정하기 (Customizing Material React Table)

 

위 링크에 이어서 세로 줄을 변경하고 로컬 스토리지에 저장해서 순서를 유지해보자.

 

아래 코드를 보완해보자.

import React, { useMemo } from "react";
import MaterialReactTable from "material-react-table";

//nested data is ok, see accessorKeys in ColumnDef below
const data = [
  {
    name: {
      firstName: "John",
      lastName: "Doe",
    },
    address: "261 Erdman Ford",
    city: "East Daphne",
    state: "Kentucky",
  },
  {
    name: {
      firstName: "Jane",
      lastName: "Doe",
    },
    address: "769 Dominic Grove",
    city: "Columbus",
    state: "Ohio",
  },
  {
    name: {
      firstName: "Joe",
      lastName: "Doe",
    },
    address: "566 Brakus Inlet",
    city: "South Linda",
    state: "West Virginia",
  },
  {
    name: {
      firstName: "Kevin",
      lastName: "Vandy",
    },
    address: "722 Emie Stream",
    city: "Lincoln",
    state: "Nebraska",
  },
  {
    name: {
      firstName: "Joshua",
      lastName: "Rolluffs",
    },
    address: "32188 Larkin Turnpike",
    city: "Charleston",
    state: "South Carolina",
  },
];

const MaterialTable = () => {
  const makeBlue = (city, name) => {
    if (name === "Doe") return <span style={{ color: "blue" }}>{city}</span>;
    return city;
  };

  //should be memoized or stable
  const columns = useMemo(
    () => [
      {
        accessorKey: "name.firstName", //access nested data with dot notation
        header: "First Name",
        size: 200,
      },
      {
        accessorKey: "name.lastName",
        header: "Last Name",
      },
      {
        accessorKey: "address", //normal accessorKey
        header: "Address",
      },
      {
        accessorKey: "city",
        header: "City",
        Cell: ({ renderedCellValue, row }) =>
          makeBlue(renderedCellValue, row._valuesCache["name.lastName"]),
      },
      {
        accessorKey: "state",
        header: "State",
        Cell: ({ renderedCellValue }) => {
          return <span style={{ color: "red" }}>{renderedCellValue}</span>;
        },
      },
    ],
    []
  );

  return (
    <MaterialReactTable
      muiTableHeadCellProps={{
        sx: {
          backgroundColor: "yellow",
          BorderStyle: "solid",
          borderWidth: "1px 0px 1px 0px",
          borderColor: "black black black black",
        },
      }}
      muiTablePaperProps={{
        elevation: 10, // shadow effect
        sx: {
          margin: "0 auto",
          width: "80%",
          border: "1px solid black",
        },
      }}
      muiTableBodyProps={{
        sx: {
          //stripe the rows, make odd rows a darker color
          "& tr:nth-of-type(odd)": {
            backgroundColor: "skyblue",
          },
        },
      }}
      columns={columns}
      data={data}
      enablePinning
    />
  );
};

export default MaterialTable;

enableColumnOrdering 옵션 추가하기

 

useMemo로 사용하였던 columns는 다음과 같이 수정한다.

  let columns = [
    {
      accessorKey: "name.firstName", //access nested data with dot notation
      header: "First Name",
      size: 10,
    },
    {
      accessorKey: "name.lastName",
      header: "Last Name",
      size: 10,
    },
    {
      accessorKey: "address", //normal accessorKey
      header: "Address",
    },
    {
      accessorKey: "city",
      header: "City",
      Cell: ({ renderedCellValue, row }) =>
        makeBlue(renderedCellValue, row._valuesCache["name.lastName"]),
    },
    {
      accessorKey: "state",
      header: "State",
      Cell: ({ renderedCellValue }) => {
        return <span style={{ color: "red" }}>{renderedCellValue}</span>;
      },
    },
  ];

 

그리고 MaterialReactTable에 enableColumnOrdering을 추가하면 된다.

  <MaterialReactTable
   	...
    data={data}
    enablePinning
    
    enableColumnOrdering
  />
</div>

 

리액트를 실행해보면 Column을 이동할 수 있다.


onColumnOrderChange로 로컬 스토리지에 순서 저장하기

 

이제 로컬 스토리지에 현재 변경된 순서를 저장해보자.

  const ACCESSOR_KEY = "ACCESSOR_KEY";

  const initOrdering = () => {
    let item = localStorage.getItem(ACCESSOR_KEY);

    if (item === null) return columns.map((c) => c.accessorKey);

    let ordering = JSON.parse(item);
    return ordering;
  };

  const handleColumnOrderChange = (value) => {
    setColumnOrder(value);

    localStorage.setItem(ACCESSOR_KEY, JSON.stringify([...value]));
  };

 

handleColumnOrderChange는 Column의 순서가 변경될 때 호출되는 onColumnOrderChange에 연결한다.

handleColumnOrderChange에 들어오는 valuecolumnsaccessorKey에 대한 배열이다.

  <MaterialReactTable
    ...
    
    enableColumnOrdering
    onColumnOrderChange={handleColumnOrderChange}
  />

 

그리고 initialStatecolumnOrder에 값을 넣고 MaterialReactTable에 추가하면 된다.

  initialState={{
    columnOrder: initOrdering,
  }}

 

이제 새로고침을 하더라도 테이블의 위치가 유지되는 것을 알 수 있다.

 

전체 코드는 다음과 같다.

import React, { useState } from "react";
import MaterialReactTable from "material-react-table";

//nested data is ok, see accessorKeys in ColumnDef below
const data = [
  {
    name: {
      firstName: "John",
      lastName: "Doe",
    },
    address: "261 Erdman Ford",
    city: "East Daphne",
    state: "Kentucky",
  },
  {
    name: {
      firstName: "Jane",
      lastName: "Doe",
    },
    address: "769 Dominic Grove",
    city: "Columbus",
    state: "Ohio",
  },
  {
    name: {
      firstName: "Joe",
      lastName: "Doe",
    },
    address: "566 Brakus Inlet",
    city: "South Linda",
    state: "West Virginia",
  },
  {
    name: {
      firstName: "Kevin",
      lastName: "Vandy",
    },
    address: "722 Emie Stream",
    city: "Lincoln",
    state: "Nebraska",
  },
  {
    name: {
      firstName: "Joshua",
      lastName: "Rolluffs",
    },
    address: "32188 Larkin Turnpike",
    city: "Charleston",
    state: "South Carolina",
  },
];

const MaterialTable = () => {
  const makeBlue = (city, name) => {
    if (name === "Doe") return <span style={{ color: "blue" }}>{city}</span>;
    return city;
  };

  let columns = [
    {
      accessorKey: "name.firstName", //access nested data with dot notation
      header: "First Name",
      size: 10,
    },
    {
      accessorKey: "name.lastName",
      header: "Last Name",
      size: 10,
    },
    {
      accessorKey: "address", //normal accessorKey
      header: "Address",
    },
    {
      accessorKey: "city",
      header: "City",
      Cell: ({ renderedCellValue, row }) =>
        makeBlue(renderedCellValue, row._valuesCache["name.lastName"]),
    },
    {
      accessorKey: "state",
      header: "State",
      Cell: ({ renderedCellValue }) => {
        return <span style={{ color: "red" }}>{renderedCellValue}</span>;
      },
    },
  ];

  const [columnOrder, setColumnOrder] = useState(
    columns.map((c) => c.accessorKey)
  );

  const ACCESSOR_KEY = "ACCESSOR_KEY";

  const initOrdering = () => {
    let item = localStorage.getItem(ACCESSOR_KEY);

    if (item === null) return columns.map((c) => c.accessorKey);

    let ordering = JSON.parse(item);
    return ordering;
  };

  const handleColumnOrderChange = (value) => {
    setColumnOrder(value);

    localStorage.setItem(ACCESSOR_KEY, JSON.stringify([...value]));
  };

  return (
    <div>
      <MaterialReactTable
        muiTableHeadCellProps={{
          sx: {
            backgroundColor: "yellow",
            BorderStyle: "solid",
            borderWidth: "1px 0px 1px 0px",
            borderColor: "black black black black",
          },
        }}
        muiTablePaperProps={{
          elevation: 10, // shadow effect
          sx: {
            margin: "0 auto",
            width: "80%",
            border: "1px solid black",
          },
        }}
        muiTableBodyProps={{
          sx: {
            "& tr:nth-of-type(odd)": {
              backgroundColor: "skyblue",
            },
          },
        }}
        columns={columns}
        initialState={{
          columnOrder: initOrdering,
        }}
        data={data}
        enablePinning
        enableColumnOrdering
        onColumnOrderChange={handleColumnOrderChange}
      />
    </div>
  );
};

export default MaterialTable;

 

결과는 링크에서 확인하자.

 

위 코드는 material-react-table 1.9.3 ver에서 동작한다.

  "dependencies": {
    ...
    "material-react-table": "^1.9.3",
    "react": "^18.2.0",
    ...
  },
반응형

댓글