React

React에서 DevExpress를 이용해 Grid Table 생성하기

칼퇴시켜주세요 2022. 2. 15. 00:44
728x90

Typescript와 React로 개발을 하던 도중 Grid Table을 구현해야 할 일이 생겨서 이곳저곳 찾아보다가 오픈소스 DevExpress Grid를 알게 되었습니다. Grid 오픈 소스 종류는 많지만 Typescript로 작업 중이여서 이 라이브러리를 쓰게 되었습니다.

 

우선 React에서 기본적으로 react-table을 가지고 테이블을 만들 수 있습니다. 한번쯤은 react-table을 이용하여 만들어 보았는 것이 좋을것 같아 사용해봤는데, 내가 느낀 장점??Customizing 하기에는 유용할 것 같다. 단점한번더 하라면 정중히 거절할것 같다.(물론 어쩔수 없이 하겠지만...) 그래서 이번 포스트에서는 쉬운방법DevExpress 오픈소스 라이브러리를 이용하여 Grid 레이아웃으로 테이블 생성을 설명하고, 다음 포스트에 react-table을 이용하여 Table을 만드는 법에 대해 설명하겠습니다. (DevExpress-Grid)

 

DevExtreme Reactive

 

devexpress.github.io

 

Installation

npm i --save @devexpress/dx-react-core @devexpress/dx-react-grid

yarn add @devexpress/dx-react-core @devexpress/dx-react-grid

material-ui

npm i --save @devexpress/dx-react-grid-material-ui

yarn add @devexpress/dx-react-grid-material-ui

bootstrap 4

npm i --save @devexpress/dx-react-grid-bootstrap4

yarn add @devexpress/dx-react-grid-bootstrap4

bootstrap 3

npm i --save @devexpress/dx-react-grid-bootstrap3

yarn add @devexpress/dx-react-grid-bootstrap3

 

Grid Table

위의 사이트에서 볼 수 있듯이 기본적으로 Grid를 이용하여 Table을 만드는 방법은 다음과 같이 간단합니다.

import React from 'react';
import Paper from '@mui/material/Paper';
import { Grid, Table, TableHeaderRow } from '@devexpress/dx-react-grid-material-ui';

const columns = [
  { name: 'id', title: 'ID' },
  { name: 'product', title: 'Product' },
  { name: 'owner', title: 'Owner' },
];
const rows = [
  { id: 0, product: 'DevExtreme', owner: 'DevExpress' },
  { id: 1, product: 'DevExtreme Reactive', owner: 'DevExpress' },
];

export default () => (
  <Paper>
    <Grid
      rows={rows}
      columns={columns}
    >
      <Table />
      <TableHeaderRow />
    </Grid>
  </Paper>
);

Grid

<Grid>는 rows, columns를 props로 가지며 Table에 들어가 데이터를 받습니다.

 

Table

<Grid>... </Grid> 사이에 <Table/>을 정의해주면 Grid의 Props인 rows, colums를 가지고 테이블을 생성해 줍니다. 

만약 이 부분을 react-table로 구현한다면 수많은 th,tr,td가 필요하지만 DevExpress Grid는 <Table />하나로 테이블이 생성이 됩니다. 

 

TableHeaderRow 

<TableHeaderRow />는 테이블의 헤더를 생성해주는 부분입니다. 

default-grid-table

 

실습

저는 Grid Table을 이용하여 파일 업로드 테이블을 만들기로 하였고 최종 화면은 다음과 같습니다.

파일 업로드

GridTable.tsx

import React, { useState } from "react";
import Paper from "@mui/material/Paper";
import {
  Grid,
  Table,
  TableHeaderRow,
  TableSelection
} from "@devexpress/dx-react-grid-material-ui";
import UploadButton from "../uploadButton/uploadButton";
import { IntegratedSelection, SelectionState } from "@devexpress/dx-react-grid";

const GridTable: React.FC = () => {
  const [selection, setSelection] = useState([]);

  const [files, setFiles] = useState([]);

  const [columns] = useState([
    { name: "FileName", title: "파일명" },
    { name: "FileSize", title: "파일 크기" },
    { name: "LastModifyDate", title: "마지막 수정 날짜" },
    { name: "UploadDate", title: "업로드 날짜" }
  ]);

  const rowData = files.map((file) => {
    const modDate = new Date(file.lastModified);
    const nowDate = new Date();
    return {
      FileName: file.name,
      FileSize: file.size,
      LastModifyDate: modDate.toISOString(),
      UploadDate: nowDate.toISOString()
    };
  });

  const onClickRemove = () => {
    let removeFile = [];
    selection.forEach((idx) => {
      removeFile.push(files[idx]);
    });

    removeFile.forEach((toRemove) => {
      const removeIdx = files.findIndex((file) => file === toRemove);
      if (removeIdx > -1) files.splice(removeIdx, 1);
    });
    setFiles([...files]);
    setSelection([]);
  };

  return (
    <div>
      <UploadButton
        type="file"
        files={files}
        setFiles={setFiles}
        onClickRemove={onClickRemove}
      />
      <Paper>
        <Grid columns={columns} rows={rowData}>
          <SelectionState
            selection={selection}
            onSelectionChange={setSelection}
          />
          <IntegratedSelection />
          <Table
            columnExtensions={[{ columnName: "FileName", width: "auto" }]}
            messages={{ noData: "파일을 업로드 하세요." }}
          />
          <TableHeaderRow />
          <TableSelection showSelectAll />
        </Grid>
      </Paper>
    </div>
  );
};

export default GridTable;

SelectionState

<SelectionState>는 Row를 선택 할 수 있게 Table Body에 체크박스를 생성해줍니다. useState로 selection 배열을 생성하고 체크박스가 체크되면 해당 row의 index를 넘겨줍니다. SelectionState를 사용하기 위해서는 <IntegratedSelection/>을 꼭 사용해야 합니다.

 

TableSelection

<TableSelection>은 전체 선택 체크 버튼을 생성해줍니다. 

UploaButton.tsx

import React from "react";
import { UploadButtonProps } from "./uploadButton.type";

const UploadButton: React.FC<UploadButtonProps> = ({
  files,
  setFiles,
  onClickRemove
}) => {
  const hiddenFileInput = React.useRef(null);

  const handleChange = (event) => {
    const uploadFile = event.target.files;
    if (uploadFile.length !== 0) {
      setFiles([...files, uploadFile[0]]);
      event.target.value = ""; // 이걸 해주지 않으면 업로드 파일 지우고 같은걸로 다시 올렸을 경우 deadLock이 발생한다.
    }
  };

  return (
    <div>
      <div>
        <button onClick={onClickRemove}>선택 삭제</button>
      </div>
      <input type="file" ref={hiddenFileInput} onChange={handleChange}></input>
    </div>
  );
};

export default UploadButton;

[Source Code]

 

mystifying-wescoff-qiyr3 - CodeSandbox

mystifying-wescoff-qiyr3 by Devconf using @devexpress/dx-react-core, @devexpress/dx-react-grid, @devexpress/dx-react-grid-material-ui, @emotion/react, @emotion/styled, @material-styled/paper, @mui/icons-material, @mui/material, react

codesandbox.io

 

반응형