diff --git a/packages/react/src/DataTable/useTable.ts b/packages/react/src/DataTable/useTable.ts index d046f736e88e..c5dbdfee23d9 100644 --- a/packages/react/src/DataTable/useTable.ts +++ b/packages/react/src/DataTable/useTable.ts @@ -48,8 +48,7 @@ export function useTable({ initialSortColumn, initialSortDirection, }: TableConfig): Table { - const [rowOrder, setRowOrder] = useState(data) - const [prevData, setPrevData] = useState(null) + const [prevData, setPrevData] = useState(data) const [prevColumns, setPrevColumns] = useState(columns) const [sortByColumn, setSortByColumn] = useState(() => { return getInitialSortState(columns, initialSortColumn, initialSortDirection) @@ -93,12 +92,14 @@ export function useTable({ } }) + const [sortedData, setSortedData] = useState(sortByColumn ? sortData({data, state: sortByColumn, headers}) : data) + // Update the row order and apply the current sort column to the incoming data if (data !== prevData) { setPrevData(data) - setRowOrder(data) + setSortedData(data) if (sortByColumn) { - sortRows(sortByColumn) + setSortedData(sortData({data, state: sortByColumn, headers})) } } @@ -112,75 +113,12 @@ export function useTable({ sortByColumn && sortByColumn.id === header.id ? transition(sortByColumn.direction) : DEFAULT_SORT_DIRECTION, } setSortByColumn(sortState) - sortRows(sortState) - } - - /** - * Sort the rows of a table with the given column sort state. If the data in the table is sparse, - * blank values will be ordered last regardless of the sort direction. - */ - function sortRows(state: Exclude) { - const header = headers.find(header => { - return header.id === state.id - }) - if (!header) { - throw new Error(`Unable to find header with id: ${state.id}`) - } - - if (header.column.sortBy === false || header.column.sortBy === undefined) { - throw new Error(`The column for this header is not sortable`) - } - - const sortMethod = - header.column.sortBy === true - ? strategies.basic - : typeof header.column.sortBy === 'string' - ? strategies[header.column.sortBy] - : header.column.sortBy - - setRowOrder(rowOrder => { - return rowOrder.slice().sort((a, b) => { - if (header.column.field === undefined) { - return 0 - } - - // Custom sort functions operate on the row versus the field - if (typeof header.column.sortBy === 'function') { - if (state.direction === SortDirection.ASC) { - // @ts-ignore todo - return sortMethod(a, b) - } - // @ts-ignore todo - return sortMethod(b, a) - } - - const valueA = get(a, header.column.field) - const valueB = get(b, header.column.field) - - if (valueA && valueB) { - if (state.direction === SortDirection.ASC) { - // @ts-ignore todo - return sortMethod(valueA, valueB) - } - // @ts-ignore todo - return sortMethod(valueB, valueA) - } - - if (valueA) { - return -1 - } - - if (valueB) { - return 1 - } - return 0 - }) - }) + setSortedData(sortData({data, state: sortState, headers})) } return { headers, - rows: rowOrder.map(row => { + rows: sortedData.map(row => { return { id: `${row.id}`, getValue() { @@ -210,6 +148,75 @@ export function useTable({ } } +/** + * Sort the rows of a table with the given column sort state. If the data in the table is sparse, + * blank values will be ordered last regardless of the sort direction. + */ +function sortData({ + data, + state, + headers, +}: { + data: Data[] + state: Exclude + headers: Header[] +}) { + const header = headers.find(header => { + return header.id === state.id + }) + if (!header) { + throw new Error(`Unable to find header with id: ${state.id}`) + } + + if (header.column.sortBy === false || header.column.sortBy === undefined) { + throw new Error(`The column for this header is not sortable`) + } + + const sortMethod = + header.column.sortBy === true + ? strategies.basic + : typeof header.column.sortBy === 'string' + ? strategies[header.column.sortBy] + : header.column.sortBy + + return data.slice().sort((a, b) => { + if (header.column.field === undefined) { + return 0 + } + + // Custom sort functions operate on the row versus the field + if (typeof header.column.sortBy === 'function') { + if (state.direction === SortDirection.ASC) { + // @ts-ignore todo + return sortMethod(a, b) + } + // @ts-ignore todo + return sortMethod(b, a) + } + + const valueA = get(a, header.column.field) + const valueB = get(b, header.column.field) + + if (valueA && valueB) { + if (state.direction === SortDirection.ASC) { + // @ts-ignore todo + return sortMethod(valueA, valueB) + } + // @ts-ignore todo + return sortMethod(valueB, valueA) + } + + if (valueA) { + return -1 + } + + if (valueB) { + return 1 + } + return 0 + }) +} + function getInitialSortState( columns: Array>, initialSortColumn?: string | number,