0

I've been struggling with this issue for a while. I would like to enable multi-column sort in react-data-grid. I cloned the repository and tried to implement a similar solution to what they had. This is what I came up with:

import DataGrid from 'react-data-grid'
...
    

export const CustomizedTable = (props: VialTableProps) => {
  const { className, columnDefs, groupBy, onCellClicked, rowData, rowHeight } =
    props
  const { onSortColumnsChange, sortColumns } = props

  const [expandedGroupIds, setExpandedGroupIds] = useState(
    (): ReadonlySet<unknown> => new Set<unknown>([])
  )

  const handleSort = (columnKey: string, direction: SortDirection) => {
    console.log('handleSort:', columnKey, direction)
    const existingSort = sortColumns.find(sc => sc.columnKey === columnKey)
    console.log('iniital order', existingSort)

    if (existingSort) {
      if (existingSort.direction === 'ASC') {
        direction = 'DESC'
      } else if (existingSort.direction === 'DESC') {
        const newSortColumns = sortColumns.filter(
          sc => sc.columnKey !== columnKey
        )
        if (onSortColumnsChange) {
          onSortColumnsChange(newSortColumns)
        }
        return
      }
    } else {
      direction = 'ASC'
    }
    console.log('new direction', direction)

    const newSortColumn: SortColumn = {
      columnKey,
      direction,
    }

    if (onSortColumnsChange) {
      onSortColumnsChange([newSortColumn])
    }
  }

  return (
      <DataGrid
        ...
        sortColumns={sortColumns}
        onSortColumnsChange={handleSort}
      />
    </div>
  )
}

I reuse this table here:

  ...
  const [sortColumns, setSortColumns] = useState<readonly SortColumn[]>([])

  function getComparator(sortColumn: SortColumn) {
    if (Array.isArray(sortColumn.columnKey)) {
      sortColumn = sortColumn.columnKey[0]
    }
    switch (sortColumn.columnKey) {
      case '***':
      case '***':
      case '***':
      case '***':
      case '***':
        return (
          a: { [x: string]: string },
          b: { [x: string]: string }
        ) => {
          if (
            typeof a[sortColumn.columnKey] === 'string' &&
            typeof b[sortColumn.columnKey] === 'string'
          ) {
            if (sortColumn.direction === 'ASC') {
              return (a[sortColumn.columnKey] as string).localeCompare(
                b[sortColumn.columnKey] as string
              )
            } else {
              return (b[sortColumn.columnKey] as string).localeCompare(
                a[sortColumn.columnKey] as string
              )
            }
          } else {
            return 0
          }
        }
      case 'subjectStatus':
      case 'queriesStatus':
        return (
          a: { [x: string]: { code: string } },
          b: { [x: string]: { code: string } }
        ) => {
          if (sortColumn.direction === 'ASC') {
            return a[sortColumn.columnKey].code.localeCompare(
              b[sortColumn.columnKey].code
            )
          } else {
            return b[sortColumn.columnKey].code.localeCompare(
              a[sortColumn.columnKey].code
            )
          }
        }
      default:
        throw new Error(`unsupported sortColumn: "${sortColumn.columnKey}"`)
    }
  }

  const sortedRows = useMemo(() => {
    console.log('useMemo called', sortColumns)
    if (sortColumns.length === 0) return subjectRows

    return [...subjectRows].sort((a, b) => {
      for (const sort of sortColumns) {
        const comparator = getComparator(sort)
        const compResult = comparator(a, b)
        if (compResult !== 0) {
          return sort.direction === 'ASC' ? compResult : -compResult
        }
      }
      return 0
    })
  }, [subjectRows, sortColumns])

  console.log('sortedRows:', sortedRows)

    return (
      <CustomizedTable
        rowData={sortedRows}
        ...
        sortColumns={sortColumns}
        onSortColumnsChange={setSortColumns}
      />
    )
  }

These are the console logs I see:

  1. When I click a column header the first time, the rows are correctly sorted in ascending order:

    1. handleSort: [{…}]0: {columnKey: '***', direction: 'ASC'}length: 1[[Prototype]]: Array(0) undefined index.tsx:47 iniital order undefined index.tsx:65 new direction ASC

When I click the same column header a second time, no sorting occurs:

handleSort: [{…}]0: {columnKey: '***', direction: 'ASC'}length: 1[[Prototype]]: Array(0) undefined
index.tsx:47 iniital order undefined
index.tsx:65 new direction ASC

My ideal behavior is that; if I click a column header once, all rows should be sorted in ascending order, a second time in descending order and a third time revert to the default

Emm
  • 2,367
  • 3
  • 24
  • 50

0 Answers0