Skip to content

Commit

Permalink
Add manual sorting props to Table for server-side sorting [MC-2868]
Browse files Browse the repository at this point in the history
  • Loading branch information
emrberk committed Jun 4, 2024
1 parent a42b454 commit 79bf0b8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
44 changes: 44 additions & 0 deletions packages/ui/__stories__/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { TextField } from '../src'

import storyStyles from './TextField.stories.module.scss'
import styles from './utils.scss'
import { SortingRule } from 'react-table'

export default {
title: 'Components/Table',
Expand Down Expand Up @@ -132,6 +133,49 @@ export const WithControlledPagination = () => {
)
}

export const WithControlledSorting = () => {
const columns = useMemo(() => getColumns({}), [])

const [loading, setLoading] = useState<boolean>(false)
// We'll start our table with initial data
const [data, setData] = useState<Person[]>(bigDataSet.slice(0, 10))
// Since we don't have real server here, we'll fake total page count.
const fetchIdRef = useRef<number>(0)
const firstUpdate = useRef(true)

// This will get called when the table needs new data.
const onSortingChange = useCallback((sortBy: SortingRule<Person>[]) => {
if (firstUpdate.current) {
firstUpdate.current = false
return
}
if (sortBy.length === 0) {
setData(bigDataSet)
return
}

// Give this fetch an ID
const fetchId = ++fetchIdRef.current

setLoading(true)

// Let's simulate server delay
setTimeout(() => {
// Only update the data if this is the latest fetch
if (fetchId === fetchIdRef.current) {
const { id, desc: isDescending } = sortBy[0]
const sortColumn = id as keyof Person
const newData = [...bigDataSet]
newData.sort((a, b) => (isDescending ? b[sortColumn] - a[sortColumn] : a[sortColumn] - b[sortColumn]))
setData(newData)
setLoading(false)
}
}, 750)
}, [])

return <Table columns={columns} data={data} loading={loading} manualSortBy onSortingChange={onSortingChange} />
}

export const WithGlobalSearch = () => {
const [searchValue, setSearchValue] = useState('')

Expand Down
23 changes: 21 additions & 2 deletions packages/ui/src/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
useColumnOrder,
useExpanded,
TableInstance,
SortingRule,
} from 'react-table'
import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'

Expand Down Expand Up @@ -176,6 +177,11 @@ export type ControlledPaginationProps = {
onPaginationChange?: (paginationChangeProps: PaginationChangeProps) => void
}

export type ControlledSortingProps<D extends object> = {
manualSortBy?: boolean
onSortingChange?: (sortBy: SortingRule<D>[]) => void
}

type CustomTableRowClickProps<D extends object> =
| {
// When using `onRowClick` it's a good practice to also make one of the cells in the table interactive by providing a button, link or something else.
Expand Down Expand Up @@ -219,7 +225,11 @@ type CustomTableProps<D extends object> = {
} & CustomTableRowClickProps<D> &
DataTestProp

export type TableProps<D extends object> = TableOptions<D> & ExtendedPaginationProps & ControlledPaginationProps & CustomTableProps<D>
export type TableProps<D extends object> = TableOptions<D> &
ExtendedPaginationProps &
ControlledPaginationProps &
ControlledSortingProps<D> &
CustomTableProps<D>

export type { ColumnType, RowType, CellType }

Expand Down Expand Up @@ -249,7 +259,9 @@ export const Table = <D extends object>({
defaultColumn = column,
disableSortBy,
onPaginationChange,
onSortingChange,
manualPagination,
manualSortBy,
onRenderedContentChange,
autoResetPage = false,
hidePagination = false,
Expand Down Expand Up @@ -338,6 +350,7 @@ export const Table = <D extends object>({
initialState,
// Tell the usePagination hook that we'll handle our own data fetching
manualPagination: manualPagination,
manualSortBy,
// This means we'll also have to provide our own pageCount
pageCount: controlledPageCount,
autoResetPage,
Expand Down Expand Up @@ -372,7 +385,7 @@ export const Table = <D extends object>({
previousPage,
setPageSize,
// Get the state from the instance
state: { pageIndex, pageSize, columnResizing, selectedRowIds },
state: { pageIndex, pageSize, sortBy, columnResizing, selectedRowIds },
setGlobalFilter,
setColumnOrder,
} = tableInstance
Expand Down Expand Up @@ -438,6 +451,12 @@ export const Table = <D extends object>({
}
}, [onPaginationChange, onPaginationChangeDebounced, pageIndex, pageSize])

useEffect(() => {
if (onSortingChange) {
onSortingChange(sortBy)
}
}, [sortBy, onSortingChange])

// Debounce our `fetchData` call for 200ms.
// We can use non-null assertion here since we're checking existence of `fetchData` in the `useEffect` below
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Expand Down

0 comments on commit 79bf0b8

Please sign in to comment.