sort! 테이블 정렬 기능 만들기

Jinjer·2023년 4월 10일
0
post-thumbnail

미리보기

결과부터 빠르게 봅시다

구현전략

🙄 서로 다른 컬럼을 가진 데이터들은 어떻게 thead를 구성해야 할까
페이지에서 column 배열을 만들어 테이블 컴포넌트에게 전달하고 내부에서 테이블 헤더를 생성한다

🤨 서로 다른 타입을 가진 데이터를 하나의 테이블에서 어떻게 분기처리 해야 할까

  1. 각각의 페이지에서 data를 테이블 컴포넌트에게 전달한다
  2. 제네릭을 이용하여 테이블 컴포넌트의 props로 받는 data를 map함수를 이용해 로우를 생성한다

😎 문자열순, 날짜순으로 정렬하도록 하려면 어떻게 구현할 수 있을까
배열의 sort함수로 data를 상황에 맞게 재가공한 뒤 반환한다

컬럼

테이블의 헤더를 구성할 헤더를 먼저 만듭니다

// pages/notice/index.tsx

function Notice() {
  const columns = [
    {
      accessor: 'title',
      value: '제목',
      sort: true,
    },
    {
      accessor: 'name',
      value: '작성자',
    },
    {
      accessor: 'createDate',
      value: '작성일',
      sort: true,
    },
  ]

  return (
    <>
      <Head>
        <title>공지사항</title>
      </Head>
      <SortTable columns={columns} />
    </>
  )
}

export default Notice

accessor: 컬럼의 Key가 됨
value: 컬럼에 표시되는 값
sort: true일 시 해당 컬럼 열의 데이터를 재정렬함

columns 정보가 담긴 데이터를 SortTable 컴포넌트로 전달한다

샘플 데이터

다음은 공지사항 목록을 생성하기 위한 데이터를 만들어 준다

export noticeData = [
{
	id: 3
	title: '테스트 글입니다3'
    createDate: '2023-04-10T14:13:52'
},
{
	id: 2
	title: '테스트 글입니다2'
    createDate: '2023-04-09T14:13:52'
},
{
	id: 1
	title: '테스트 글입니다'
    createDate: '2023-04-08T14:13:52'
},
]

이제 생성한 데이터와 컬럼 정보를 받을 컴포넌트를 만들어 보죠

테이블 컴포넌트

// components/SortTable/index.tsx
import React, { useState, useMemo } from 'react'

interface SortTableProps<T> {
  columns: ColumnsProps[]
  data?: T[]
  renderItem: (item: T) => React.ReactNode
}

interface ColumnsProps {
  accessor: string
  value: string
  sort?: boolean
}

function SortTable<T extends unknown>({
  columns,
  data = [],
  renderItem,
}: SortTableProps<T>): JSX.Element {
  const [order, setOrder] = useState('')
  const [toggle, setToggle] = useState(true)

  const makeSortData = () => {} // 여기서 데이터를 재정렬함

  // [3]
  const sortedData = useMemo(() => makeSortData(), [toggle])

  // [2]
  const handleDataToggle = (accessor: string) => {
    setOrder(accessor)
    setToggle(!toggle)
  }
	
  // [1]
  const headerGroup = columns.map(column =>
    column.sort ? (
      <TableHeadCell key={`table-head-${column.value}`}>
        {column.value}
        <p onClick={() => handleDataToggle(column.accessor)}>리스트 재정렬</p>
      </TableHeadCell>
    ) : (
      <TableHeadCell key={`table-head-${column.value}`}>{column.value}</TableHeadCell>
    ),
  )

  return (
    <TableWrapper>
      <Table>
        <TableHead>
          <tr>{headerGroup}</tr>
        </TableHead>
        <TableBody>
          {sortedData?.map((item, index) => (
            <tr key={`table-row-${index}`}>{renderItem(item)}</tr>
          ))}
        </TableBody>
      </Table>
    </TableWrapper>
  )
}

export default SortTable
  1. headerGroup 함수를 호출해서 테이블의 HEAD영역을 렌더링 해준다
  2. 리스트 재정렬을 클릭하면 handleDataToggle 함수가 실행된다
  3. makeSortData 함수가 실행되고 재정렬된 데이터를 다시 렌더링 하게 된다

정렬

마지막으로 원하는 조건에 맞춰 리스트를 재정렬 해본다

const makeSortData = () => {
    switch (order) {
      case 'title':
        return data.sort((a, b) => (a > b ? 1 : -1))
      case 'createDate':
        return data.sort((a, b) =>
          !toggle
            ? new Date(a[order]).getTime() - new Date(b[order]).getTime()
            : new Date(b[order]).getTime() - new Date(a[order]).getTime(),
        )
      default:
        return data
    }
  }

위의 코드에서는 컬럼의 키에 따라 문자열과 날짜순으로 정렬하였지만
case를 추가하여 가나다순 혹은 특정 값에 따라 정렬 할 수도 있다.

profile
프론트엔드개발자

0개의 댓글