-
TanStack Table v8 - Merge header cell (헤더 병합)Front-end/React 2024. 3. 7. 11:57반응형
이번 리액트 프로젝트에서 처음 사용해보는 라이브러리들이 꽤있다.
그 중 하나가 TanStack Table이고, 사용한 버전은 v8 이다.
https://tanstack.com/table/latest/docs/introduction
일반적인 테이블은 문서를 봐가면서 따라하면 그리 어렵지 않게 사용할 수 있다.
그런데 이번에는 중간 중간에 헤더가 합쳐져 있는 것을 구현해야했다.
+ Shadcn을 사용했지만 일반 html tag도 상관 없다
일반 테이블 만들기 ( Normal Table )
일반테이블은 문서를 보면 알 수 있지만 생각 보다 쉽게 할 수 있고 다양하게 커스터마이징도 가능하다.
기본적으로 React에서 TanStack Table을 사용할 때는 useReactTable이라는 것을 가져와서 사용하게 된다.
그리고 그 안에는 options를 넣어서 사용하게 되는데, data, columns 등을 넣어서 사용한다.
예시를 보면 아래와 같다.
const table = useReactTable({ data, columns });
그렇다면 data와 columns는 각각 무엇을 의미할까?
말 그대로 테이블에서 사용할 data와 columns인데, 예시를 보자면 아래와 같다.<data>
[ { "userId": 1, "userName": "홍길동", "userPhoneNumber": 01012345678, } ... ... ]
<columns>
interface User { userId: string; userName: string; userPhoneNumber: string; } const columns: ColumnDef<User>[] = [ { accessorKey: 'userId', header: '특정 아이디', cell: ({ row }) => { const id = row.getValue('userId') ?? ''; if (id > 5) { return ( <p className="text-red-700">{name}</p> ); } return <p className="text-blue-300">{name}</p>; } }, { accessorKey: 'userName', header: '고객명', cell: ({row}) => { return <span>{`${row.original.id} - `${row.getValue()}`}</span> } }, { accessorKey: 'userPhoneNumber', header: '전화번호', cell: ({ row }) => { return ( <div className="border-2 border-red-300"> {row.getValue() || '전화번호가 없습니다'} </div> ); } } ]
다른 것보다 TanStack Table을 사용하면서 columns 부분에서 편함을 많이 느꼈다.
각 columns 안에서 useState, useEffect 같은 hooks 또한 사용 가능해서 cell 안에서 얼마든지 커스터마이징을 한 후에 Table cell로 내보낼 수 있다는 장점이 굉장히 편하게 느껴졌다.
병합 헤더 만들기 ( Merge header cell )
그렇다면 헤더를 병합해서 사용할 수 있는 방법도 알아보자.
자칫 방법을 잘 못 하면 헤더가 2개의 row로 나뉘어져서 이상하게 보여질 수 있으니 조심하자!
방법은 기본적인 Table을 만드는 것과 다르지 않지만 columns를 만들 때 추가해줘야할 것이 있다.
우선 createColumnHelper를 import 해오고 이것을 사용해야한다.
import { createColumnHelper } from '@tanstack/react-table'; const columnHelper = createColumnHelper<User>(); const columns = [ columnHelper.accessor('userId', { id: 'userId', header: '유저 아이디', cell: (info) => info.getValue(), meta: { rowSpan: 2 } }), columnHelper.group({ id: 'userInfo', // 그룹아이디를 입력해주세요 header: '유저 정보', // 2개의 Row 중 상단에 들어갈 그룹 헤더의 제목을 입력해주세요 columns: [ columnHelper.accessor((row) => row.userName, { id: 'userName', cell: (info) => info.getValue(), header: '유저명' }), columnHelper.accessor((row) => row.gender, { id: 'gender', cell: (info) => info.getValue(), header: '성별' }), columnHelper.accessor('age', { id: 'age', cell: (info) => info.getValue(), header: '나이' }) ] }), columnHelper.accessor('userPhoneNumber', { id: 'userPhoneNumber', header: '전화번호', cell: (info) => info.getValue(), meta: { rowSpan: 2 } }) ]
위처럼 작성해주면 좌우에 rowSpan이 적용되고, 가운데가 병합이 되어있는 헤더를 만날 수 있다.
하나를 보자면 columnHelper.group 안에서 columnHelper.accessor 안에 보면 row를 이용해서 하는 방법이 있고, id를 사용하는 방법이 있는데 어떤 것으로 하던 무방하다!
여기서 끝이 아니라 Table Header를 렌더링 해주는 부분에 하나 더 추가를 해줘야한다.
우리는 meta라는 이름으로 rowSpan을 넣어놨으므로 그것을 따로 정의해서 넘겨주어야하는 것이다.
<TableHeader> {tableInstance.getHeaderGroups().map((headerGroup, index) => ( <TableRow key={headerGroup.id} className="bg-blue-200"> {headerGroup.headers.map((header) => { const rowSpan = (header.column.columnDef.meta as any)?.rowSpan; if ( !header.isPlaceholder && rowSpan !== undefined && header.id === header.column.id ) { return null; } return ( <TableCell key={header.id} colSpan={header.colSpan} rowSpan={rowSpan}> {flexRender( header.column.columnDef.header, header.getContext() )} </TableCell> ); })} </TableRow> ))} </TableHeader>
나의 경우 Shadcn을 사용하고 있으므로 이렇게 했다.
이렇게 넘겨주게 되면 rowSpan이 적용되면서 원하는대로 모양이 나타나게 된다.
그래서 모양만 잘 만들면 위와 같이 나타나도록 할 수 있다.
어떤 사람들은 Table 만들 때 TanStack Table 사용하지 않으면 못 만들겠다고 하던데, 나도 그 지경까지 온 것 같다.
편리함을 알아버린 것 같다...
반응형'Front-end > React' 카테고리의 다른 글
ReactJS의 디자인 패턴에 대해서 알아보자! (0) 2024.05.22 리액트(React) 19버전 업데이트 전! 18버전 훑어보기! (0) 2024.05.21 LocalStorage로 저장, 불러오기, 삭제 (JS, React) (2) 2023.02.05 리액트 파일 업로드, 파일 다운로드 File upload, download with javascript react (2) 2022.06.24 React 상태 관리 : Recoil 로 해보자! (0) 2021.12.04