[React] react-table + typescript

0후·2022년 2월 27일
1

프론트엔드

목록 보기
21/41
  1. yarn add react-table 로 react-table 설치
  2. yarn add @types/react-table 로 typescript 버전으로도 설치
  3. src 폴더 내 components란 폴더 생성해준다.
  4. 테스트를 위해서 components 폴더 안에 더미데이터 파일을 넣어준다. 더미데이터는 Mockaroo 에서 손쉽게 제작할 수 있다. 나는 json 파일로 만들어서 200개의 데이터를 만들고 다운로드 받았다.
  • src/components/MOCK_DATA.json
[
{"id":1,"first_name":"Dallis","last_name":"Balchen","email":"dbalchen0@craigslist.org","gender":"Female"},
{"id":2,"first_name":"Jarred","last_name":"Lias","email":"jlias1@statcounter.com","gender":"Male"},
{"id":3,"first_name":"Doralynne","last_name":"McGarrahan","email":"dmcgarrahan2@fema.gov","gender":"Female"},
{"id":4,"first_name":"Thatch","last_name":"Belk","email":"tbelk3@ycombinator.com","gender":"Male"},
{"id":5,"first_name":"Dwain","last_name":"Ledwitch","email":"dledwitch4@paginegialle.it","gender":"Male"}
  // ... 중략
]
  1. components 폴더 안에 columns.ts 란 파일 생성 후 더미데이터 안에 있는 내용을 참조하여 header와 accessor를 작성해준다. header는 테이블 헤더에 나올 텍스트고, accessor는 json 파일의 key값을 말한다.
  • src/components/columns.ts
export const COLUMNS = [
    {
        Header : 'Id',
        accessor : 'id'
    },
    {
        Header : 'First Name',
        accessor : 'first_name'
    },
    {
        Header : 'Last Name',
        accessor : 'last_name'
    },
    {
        Header : 'Email',
        accessor : 'email'
    },
    {
        Header : 'Gender',
        accessor : 'gender'
    }
];
  1. components 폴더 안에 PaginationTable.tsx란 파일 생성 후 그 안에 하단처럼 내용을 작성해준다.
  • src/components/PaginationTable.tsx
import React, { useMemo } from 'react';
import MOCK_DATA from './MOCK_DATA.json'
import { COLUMNS } from './columns'
import { usePagination, useTable } from 'react-table'
import './table.css'

export const PaginationTable = () => {
    const columns = useMemo(() => COLUMNS, [])
    const data = useMemo(() => MOCK_DATA, [])

    const { 
        getTableProps, 
        getTableBodyProps, 
        headerGroups, 
        page,
        nextPage,
        previousPage,
        canNextPage,
        canPreviousPage,
        pageOptions,
        gotoPage,
        pageCount,
        setPageSize,
        state,
        prepareRow,
    } = useTable({
            // @ts-ignore
            columns,
            data,
        },
        usePagination
    );

    const { pageIndex, pageSize } = state

    return (
        <div className="table">
            <table {...getTableProps()}>
                <thead>
                    {headerGroups.map((headerGroup) => (                   
                        <tr {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map((column) => (
                                <th {...column.getHeaderProps()}>
                                    {column.render('Header')}
                                </th>
                            ))}
                        </tr>
                    ))}
                </thead>

                <tbody {...getTableBodyProps()}>
                    {page.map((row: any) => {
                        prepareRow(row)
                        return (
                            <tr {...row.getRowProps()}>
                                {row.cells.map((cell: any) => {
                                    return (
                                        <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                                    );
                                })}
                            </tr>
                        );
                    })}
                </tbody>
            </table>

            <div className="table-pagination" style={{margin: '5px', display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
                <button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
                    {'<<'}
                </button>
                <button onClick={() => previousPage()} disabled={!canPreviousPage}>
                    Previous
                </button>
                <span>
                    <strong style={{display: 'block', width: '100px', textAlign: 'center'}}>
                        {pageIndex + 1} / {pageOptions.length} 
                    </strong>
                </span>
                <span>
                    Go to page: {' '}
                    <input type="number" defaultValue={pageIndex + 1}
                    onChange={(e) => {
                        const pageNumber = e.target.value ? Number(e.target.value) - 1 : 0 
                        gotoPage(pageNumber)
                    }} 
                    style={{width: '50px'}} />
                </span>
                <button onClick={() => nextPage()} disabled={!canNextPage}>
                    Next
                </button>
                <button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
                    {'>>'}
                </button>
            </div>
            <div className="table-pagesize" style={{margin: '5px', display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
                <select value={pageSize} onChange={(e) => setPageSize(Number(e.target.value))}>
                    {
                        [10, 25, 50].map(pageSize => (
                            <option key={pageSize} value={pageSize}>
                                {pageSize}개 씩 보기
                            </option>
                        ))
                    }
                </select>
            </div>
        </div>
    );
}

export default PaginationTable;
  1. 6을 직접 따라치든, 복붙하든 에러가 나는데, 두 가지 이유이다. 하나는 css파일이 없어서이고, 두번째는 react-table에서 사용하는 인스턴스를 선언해주지 않아서 그렇다.
  2. css 파일은 다음과 같다.
  • src/components/table.css
.table {
    margin: 20px 0;
}
table {
    font-family: Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    width: 100%;
    font-size: 12px;
}
table td, table th {
    border: 1px solid #ddd;
    padding: 8px;
}
table tr:nth-child(even){
    background-color: #f2f2f2;
}
table tr:hover {
    background-color: #ddd;
}
table th {
    padding-top: 12px;
    padding-bottom: 12px;
    text-align: left;
    background-color: #04AA6D;
    color: white;
}
  1. 이번엔 components 폴더 안에 넣어주지 않고, src 안에다가 react-table-config.d.ts 파일을 만들어주고 하단처럼 작성해준다.
  • src/react-table-config.d.ts
import {
    UsePaginationInstanceProps,
    UsePaginationOptions,
    UsePaginationState
  } from 'react-table'
  
  declare module 'react-table' {
    export interface TableOptions<D extends Record<string, unknown>>
      extends UsePaginationOptions<D> {}
  
    export interface TableInstance<D extends Record<string, unknown> = Record<string, unknown>>
      extends UsePaginationInstanceProps<D> {}
  
    export interface TableState<D extends Record<string, unknown> = Record<string, unknown>>
      extends UsePaginationState<D> {}
  }
  1. 위의 과정을 다 했으면 이제 적용해 줄 차례다. App.tsx에서 PaginationTable을 import 해주고, 테이블을 넣고자 하는 곳에 <PaginationTable /> 을 선언해준다. 예시는 다음과 같다.
import { PaginationTable } from './components/PaginationTable'

function App() {
	return (
    	<div className="App-board">
          <PaginationTable />
        </div>
    )
}

export default App;
profile
휘발방지

1개의 댓글

comment-user-thumbnail
2022년 11월 14일

안녕하세용 ~! 게시글따라서 표를 작성중인데 혹시 날짜와 몇개의 셀들은 함수로 가공 하여 데이터를 뿌려야할때는 어떻게 할수 있는지 질문 남겨도 괜찮을까용? 정보 공유 감사합니당 ~!

답글 달기