A summary of notable changes per release. For the full commit history see the repository on GitHub.
- A custom
progressComponentcould not be shown on the initial load — the skeleton rows always won. NewprogressSkeletonprop (defaulttrue) lets you set it tofalseto show yourprogressComponenton initial load instead. → Loading state
- Context menu — new
contextMenuprop adds a menu to header cells and rows, opened by right-click, a kebab (⋮) button, or both. The header menu ships built-in actions (sort ascending/descending, clear sort, pin left/right, unpin, hide column, reset); row menus render consumer-supplied actions viacontextMenuActions.row, and every selection firesonContextMenuAction. Fully keyboard-accessible (role="menu", arrow keys, Escape with focus return), RTL-aware, and localizable vialocalization.contextMenu(all bundled locales translated). → Context menu (#1342) - bigint and Date selectors —
Primitivenow includesbigintandDate, so selectors can return them directly for display and built-in sorting.bigintrenders as its decimal string andDateas a locale string. → Columns
- Selectors that return
nullorundefined(e.g. a missing field) now sort to the end in both directions instead of landing in an arbitrary position. → Sorting - Pagination now sizes its layout from its own container instead of the window, fixing squeezed/overlapping controls in narrow containers and mobile viewports. → Pagination
- Fixed a pagination SSR hydration mismatch that made React re-render the table client-side on wide viewports.
- Skeleton loading rows now stretch to the full table width instead of fixed cell widths. → Loading state
- Widened the column resize handle and fixed the neighboring header cell stealing half its grab area; the hover indicator is now centered on the column separator, including under RTL. → Resizable columns
-
Column resize and reorder (including column groups) now work on touch devices. Resize handles respond to touch drags; reorder uses a short press-and-hold to grab a header so a normal swipe still scrolls the table. → Column reordering
-
Fixed the native sort icon animating (fading and spinning) as it disappeared when a column returned to the unsorted state; it now clears immediately. → Sorting
-
Fixed column filter menus on touch devices: the menu no longer flickers open/closed when tapping the filter icon, and filter icons on the leftmost/rightmost columns now open reliably with the panel clamped on-screen. → Filtering
- Fixed RTL support across resizing, pinning, and separators: resize handles sit on the correct edge and widen as in LTR, pinned columns stick to logical edges with mirrored shadows, the pinned horizontal scrollbar accounts for RTL scroll coordinates, and column/group-header separators plus small chrome (filter dot, select arrows, pagination chevron) mirror correctly. Applies to
direction={Direction.RTL}and inheriteddir="rtl". → RTL support - Fixed row and table backgrounds cutting off at the initial container width when the table scrolls horizontally, leaving scrolled-into columns unpainted. → Theming
- Fixed
fixedHeaderwithresponsive={false}not creating a scroll container, letting rows spill over content below the table.fixedHeadernow always creates one. - Fixed the pinned-columns scrollbar failing to appear or going stale when content width changed without a container resize (async rows, resizing or toggling columns), and when columns were pinned with
responsive={false}. → Column pinning - Fixed resize handles being clipped for right-pinned columns and the last column, which cut their hit areas down to a sliver. → Resizable columns
- Fixed pin-band separators: replaced the blurred edge shadow with a crisp boundary line (
--rdt-color-pin-border, replacing--rdt-color-pin-shadow), and closed missing separators and broken row dividers around the right pin band. → Column pinning - Fixed open column-filter panels floating detached from their column on scroll; they now close on scroll and window resize.
- Keyboard cell navigation — new
cellNavigationprop turns the table into a WAI-ARIA grid (role="grid"/"gridcell", single Tab stop, roving tabindex). Arrow keys move between cells, including the header row, selection checkboxes, and expander buttons;Home/EndandCtrl+Home/Ctrl+Endjump to row and grid edges;Enter/F2open a cell's editor andEscapecancels it;Enter/Spacesort from a header. → Keyboard navigation (#1332) - More headless hooks —
useCellNavigation(the same logic behindcellNavigation, usable on your own markup) anduseColumnResize(drag-to-resize) are now exported. Column pinning gets three new pure-function exports —getPinnedOffsets,getPinnedTotalWidths,getPinnedCellMeta— since pinning has no state to own beyondcolumn.pinnedon your own columns. → Headless hooks
- Fixed inline-edit refocus resolving by DOM id, which could steal focus into a different
DataTableinstance on the same page when two tables shared column ids and row keys.
- Fixed a table-level
sortFunctionnot being called when a column's sort was cycled to the "not sorted" state, which broke patterns like pinning rows to the top regardless of sort. → Row pinning
- The expandable-row toggle button's hover/focus highlight is now sized to the icon instead of filling the entire cell.
- Fixed
selectableRowsComponentPropsresolving only the last entry when multiple function-valued props were passed — all function props now resolve correctly. → Row selection
- Fixed a crash (
Cannot read properties of null (reading 'columnId')) that tore down the table at the end of nearly every column resize drag under React 18. (#1326)
- Removable sorting — clicking a sorted header now cycles asc → desc → unsorted, so a sort can be cleared without reloading the page. → Sorting docs
- Multi-column sorting — new
sortMultiprop. Ctrl/⌘-click headers to build a sort stack; priority follows click order and a numbered badge marks each sorted column. → Sorting docs (#1325) SortColumn<T>type exported — represents a single entry in the sort stack ({ column, sortDirection }).onSortgains a fourthsortColumns: SortColumn<T>[]argument with the full sort config. Existing three-argument handlers are unaffected.
- A third click on a sorted header now removes the sort (previously it stayed on descending). Server-side
onSorthandlers should treat an emptysortColumnsarray as "no sort" and drop theirORDER BY.
- Localization — new
localizationprop replaces the three separate option props (columnFilterOptions,expandableRowsOptions, and pagination aria-label fields onpaginationComponentOptions). Pass a single object to translate every string and aria-label in the table — filter panel, pagination navigation, and expand/collapse buttons. → Localization docs - Built-in locales — import pre-built translations from the
react-data-table-component/localessubpath. Ships with: English (en), French (fr), Spanish (es), German (de), Brazilian Portuguese (ptBR), Arabic — Modern Standard (ar), Egyptian (arEG), Levantine (arLV), Hebrew (he), Chinese Simplified (zhCN), Chinese Traditional (zhTW), Japanese (ja), Korean (ko), Ukrainian (uk). Each locale is individually tree-shakeable. - New utility exports:
emptyFilterState(type)andisFilterActive(filter). → Filtering docs - Removable sorting — clicking a sortable header now cycles ascending → descending → unsorted, so a sort can be cleared directly from the header. → Sorting docs
- Multi-column sorting — new
sortMultiprop. Ctrl/⌘-click a header to add it to the existing sort; priority follows click order and a numbered badge marks each sorted column.onSortgains a fourthsortColumnsargument with the full sort config, and the newSortColumn<T>type is exported. → Sorting docs
- A third click on a sorted header now removes the sort (previously it stayed descending). When the sort is cleared,
onSortfires with an empty primary column and an emptysortColumnsarray — server-side handlers should treat this as "no sort" and drop theirORDER BY. The existing three-argumentonSortusage is unaffected; the fourth argument is additive.
The following will continue to work in 8.x but will be removed in v9. TypeScript will show a deprecation hint.
columnFilterOptionsprop — uselocalizationwith afilterkey instead.expandableRowsOptionsprop — uselocalizationwith anexpandablekey instead.- Pagination aria-label fields on
paginationComponentOptions(navigationAriaLabel,firstPageAriaLabel,previousPageAriaLabel,nextPageAriaLabel,lastPageAriaLabel) — uselocalizationwith apaginationkey instead. ColumnFilterOptionsandExpandableRowsOptionstypes — useLocalization['filter']andLocalization['expandable']instead.
paginationPosition— controls where the pagination bar renders. Accepts'bottom'(default),'top', or'both'. → Pagination docspaginationPage— controlled active-page prop. Set it to navigate programmatically (e.g. reset to page 1 after a filter change). Use withonChangePageto keep in sync. → API reference- Built-in footer row for totals, averages, and other summary cells. Declare per-column with the new
footerfield (ReactNodeor(rows) => ReactNode) or replace the whole row withfooterComponent. Footer cells respect column widths, alignment, and pinning automatically. → Footer docs - Pagination button aria-labels — "First Page", "Previous Page", "Next Page", and "Last Page" are now configurable via
paginationComponentOptions, enabling proper i18n for screen readers. ref.clearSort()— newDataTableHandlemethod to programmatically reset sort back to its default state, or unsorted if no defaults are set. → Sorting docs- Sortable column indicator — sortable columns now show a faint sort icon at reduced opacity so users can discover which columns are sortable before clicking. The inactive opacity is themable via
--rdt-sort-icon-inactive-opacity(default0.3). onScroll— new prop that fires whenever the table's scroll wrapper scrolls. Receives the nativeReact.UIEvent<HTMLDivElement>.
- Fixed column reordering bypassing
reorder={false}when a cell's text was selected via double-click and then dragged.
- Inline editing now supports
number,date,checkbox, andcustomeditor types. New column-levelvalidatehook gates the edit beforeonCellEditfires. → Inline editing - Shift-click range selection on row checkboxes. Enabled by default — opt out with
selectableRowsRange={false}. NewselectedRowsprop drives controlled selection. → Row selection - New headless export hook
useTableExport: build CSV/JSON, trigger a download, or copy to clipboard. → Export
- Expandable row open/close animation now works correctly. Switched from a
max-heighttween to the CSS gridgrid-template-rows: 0fr → 1frtrick. Close animation added — the row stays mounted while animating out, then unmounts. Both directions respectanimateRowsandprefers-reduced-motion. - Fixed
useLayoutEffectSSR warning in Next.js App Router and Astro SSR modes. - Inline editing: added CSS for
checkboxandcustomeditor types, and validation error tooltip styles (.rdt_cellEditError,.rdt_editErrorTip).
v8 is a full rewrite around a headless hook architecture. Every major feature is composable and usable independently of <DataTable>. See the migration guide for breaking changes from v7.
- Column pinning (
pinned: 'left' | 'right') with cascading sticky offsets, custom pinned scrollbar, and full compatibility with resize/reorder/fixed-header. - Inline cell editing (
editable+onCellEdit). - Per-column filtering with structured operators (
filterable,filterType, controlledfilterValues). - Column groups (
columnGroups): span labels across adjacent columns. Drag-to-reorder entire groups as a unit. - Drag-to-reorder columns and column groups (
reorder: true,onColumnOrderChange). - Column visibility hook (
useColumnVisibility) for show/hide pickers. - Resizable columns (
resizable): handle straddles the column boundary, 6 px hit area, 40 px hard floor. - Column separators:
columnSeparatorandheaderSeparatorwith"subtle"/"full"variants. - Row animations (
animateRows): staggered entrance + sort transitions, respectsprefers-reduced-motion. - Improved loading state: skeleton on first load, dimmed overlay + spinner on refetch.
- Imperative ref API:
ref.current?.clearSelectedRows(). TheclearSelectedRowsprop is deprecated. - New row events:
onRowMiddleClicked,onRowMouseEnter,onRowMouseLeave. - Dark mode support via
colorMode("light", "dark", "auto"). - Headless hooks exported:
useColumns,useTableState,useTableData,useColumnFilter,useColumnVisibility. - New theme:
crisp. Refactored theme system around CSS variables (createTheme).
- Replaced styled-components with CSS variables and a single stylesheet. No more runtime CS -in-JS. Smaller bundle, faster first render.
- All visual defaults live in
DataTable.cssas--rdt-*custom properties. - Row separators are drawn at the cell level (
.rdt_cellBase) instead of the row container. Fixes a long-standing issue where the separator scrolled with content past pinned columns. - System column width (checkbox/expander) is now controlled by
--rdt-system-col-width. Themes can override it and pinning offsets stay aligned.
- v8 ships its own CSS. No
import 'react-data-table-component/dist/index.css'required, and styled-components overrides will not apply. Use the new theme system orcustomStyles. clearSelectedRowsprop deprecated in favor ofref.current.clearSelectedRows().- Several renamed props and removed legacy options. See migration guide.
v7 is no longer actively developed. Docs remain at v7.reactdatatable.com.
If you're upgrading, the migration guide covers the breaking changes and rename mappings.