Home

Awesome

rsuite-table

A React table component.

npm GitHub Actions Coverage Status

Features

Preview

More Examples

Install

# use npm
npm i rsuite-table

# or use yarn
yarn add rsuite-table

# or use pnpm
pnpm add rsuite-table

Usage

import { Table, Column, HeaderCell, Cell } from 'rsuite-table';
import 'rsuite-table/lib/less/index.less'; // or 'rsuite-table/dist/css/rsuite-table.css'

const dataList = [
  { id: 1, name: 'a', email: 'a@email.com', avartar: '...' },
  { id: 2, name: 'b', email: 'b@email.com', avartar: '...' },
  { id: 3, name: 'c', email: 'c@email.com', avartar: '...' }
];

const ImageCell = ({ rowData, dataKey, ...rest }) => (
  <Cell {...rest}>
    <img src={rowData[dataKey]} width="50" />
  </Cell>
);

const App = () => (
  <Table data={dataList}>
    <Column width={100} sortable fixed resizable>
      <HeaderCell>ID</HeaderCell>
      <Cell dataKey="id" />
    </Column>

    <Column width={100} sortable resizable>
      <HeaderCell>Name</HeaderCell>
      <Cell dataKey="name" />
    </Column>

    <Column width={100} sortable resizable>
      <HeaderCell>Email</HeaderCell>
      <Cell>
        {(rowData, rowIndex) => {
          return <a href={`mailto:${rowData.email}`}>{rowData.email}</a>;
        }}
      </Cell>
    </Column>

    <Column width={100} resizable>
      <HeaderCell>Avartar</HeaderCell>
      <ImageCell dataKey="avartar" />
    </Column>
  </Table>
);

API

<Table>

PropertyType (Default)Description
affixHeaderboolean, numberAffix the table header to a specified position on the page.
affixHorizontalScrollbarboolean, numberAffix the table's horizontal scrollbar to a specified position on the page.
autoHeightbooleanAutomatically expand the table's height based on the number of data rows, without displaying a vertical scrollbar.
borderedbooleanDisplay table borders.
cellBorderedbooleanDisplay cell borders.
children(components: { Cell, HeaderCell, Column, ColumnGroup }) => ReactNode | ReactNodeRender props that receive parameterized Cell, HeaderCell, Column, and ColumnGroup components, making TypeScript usage more convenient.
data *RowData[]Table data.
defaultExpandAllRowsbooleanExpand all rows by default.
defaultExpandedRowKeysstring[]Specify the initially expanded rows by their keys.
defaultSortType'desc' | 'asc'Default sort type.
expandedRowKeysstring[]Specify the expanded rows by their keys (Controlled).
fillHeightbooleanForce the table's height to match its parent container's height. Cannot be used with autoHeight.
headerHeightnumber (40)Table header height.
heightnumber (200)Table height.
hoverboolean (true)Enable row hover effects.
isTreebooleanDisplay the table as a tree structure.
loadingbooleanShow a loading state.
locale{emptyMessage: string, loading: string}Messages for empty data and loading states.
maxHeightnumberMaximum table height.
minHeightnumber (0)Minimum table height.
onExpandChange(expanded: boolean, rowData: RowData) => voidCallback function triggered when a tree table node is expanded or collapsed.
onRowClick(rowData: RowData, event: SyntheticEvent) => voidCallback function triggered when a row is clicked, returning the row data.
onRowContextMenu(rowData: RowData, event: SyntheticEvent) => voidCallback function triggered by a context menu event, returning the row data.
onScroll(scrollX: object, scrollY: object) => voidCallback function for scrollbar scroll events.
onSortColumn(dataKey: string, sortType: string) => voidCallback function triggered when the sort order changes, returning the column key and sort type.
renderEmpty(info: ReactNode) => ReactNodeCustom content to display when there is no data.
renderLoading(loading: ReactNode) => ReactNodeCustom content to display during data loading.
renderRow(children?: ReactNode, rowData?: RowData) => ReactNodeCustom row element renderer.
renderRowExpanded(rowData?: RowData) => ReactNodeCustom content to display in an expanded row.
renderTreeToggle(icon: ReactNode, rowData: RowData, expanded: boolean) => ReactNodeCustom toggle icon for expanding/collapsing tree nodes.
rowClassNamestring, (rowData: RowData, rowIndex: number) => stringAdd an optional custom class name to rows.
rowExpandedHeightnumber (100), (rowData?: RowData) => numberSet the height of expanded rows.
rowHeightnumber (46), (rowData: RowData) => numberRow height.
rowKeystring ('key')Unique key for each row, derived from data.
rtlbooleanEnable right-to-left layout.
shouldUpdateScrollboolean, (event) => ({ x, y }) (true)Determine whether to update the scroll position after the table size changes.
showHeaderboolean (true)Display the table header.
sortColumnstringName of the column to sort by.
sortType'desc' | 'asc'Sort type (Controlled).
virtualizedbooleanEfficiently render large datasets.
widthnumberTable width.
wordWrapboolean | 'break-all' | 'break-word' | 'keep-all'Control text wrapping behavior within cells.

<Column>

PropertyType (Default)Description
align'left' | 'center' | 'right'Sets the text alignment within the column.
colSpannumberMerges cells within the column when the dataKey value for the merged cells is null or undefined.
fixedboolean | 'left' | 'right'Fixes the column to the left or right side of the table.
flexGrownumberAutomatically adjusts the column width based on the value of flexGrow. Cannot be used with resizable and width properties.
fullTextbooleanDisplays the full text of the cell content when the mouse hovers over it.
minWidthnumber (200)Sets the minimum width of the column when using flexGrow.
onResize(columnWidth?: number, dataKey?: string) => voidCallback function triggered after the column width changes.
resizablebooleanAllows the column width to be resized.
rowSpan(rowData: RowData) => numberMerges rows in the specified column.
sortablebooleanEnables sorting on the column.
treeColbooleanIndicates that the column is part of a tree structure.
verticalAlign'top' | 'middle' | 'bottom'Sets the vertical alignment of content within the column.
widthnumberSpecifies the column width.

sortable is used to define whether the column is sortable, but depending on what key sort needs to set a dataKey in Cell. The sort here is the service-side sort, so you need to handle the logic in the ' Onsortcolumn ' callback function of <Table>, and the callback function returns sortColumn, sortType values.

<ColumnGroup>

PropertyType (Default)Description
align'left' | 'center' | 'right'Sets the text alignment within the column group.
fixedboolean | 'left' | 'right'Fixes the column group to the left or right side of the table.
groupHeaderHeightnumberSets the height of the group header. The default value is 50% of the table's headerHeight.
headerReactNodeSpecifies the content to be displayed as the group header.
verticalAlign'top' | 'middle' | 'bottom'Sets the vertical alignment of content within the column group.

<HeaderCell>

PropertyType (Default)Description
childrenReactNodeSpecifies the content to be displayed in the column header.
renderSortIcon(sortType) => ReactNodeCustomizes the rendering of sort icons on column headers.

<Cell>

PropertyType (Default)Description
childrenReactNode | ((rowData: RowData, rowIndex?: number) => ReactNode)The content to be displayed in the cell.
dataKeystringThe key used for data binding and sorting.
rowDataRowDataThe data associated with the current row.
rowIndexnumberThe index of the current row.

There are three ways to use <Cell>, as follows:

<Column width="{100}" align="center">
  <HeaderCell>Name</HeaderCell>
  <Cell dataKey="name" />
</Column>
const NameCell = ({ rowData, ...props }) => (
  <Cell {...props}>
    <a href={`mailto:${rowData.email}`}>{rowData.name}<a>
  </Cell>
);

<Column width={100} align="center">
  <HeaderCell>Name</HeaderCell>
  <NameCell />
</Column>
<Column width={100} align="center">
  <HeaderCell>Name</HeaderCell>
  <Cell>
    {(rowData, rowIndex) => {
      return <a href={`mailto:${rowData.email}`}>{rowData.name}</a>;
    }}
  </Cell>
</Column>

(For nested data read this: https://github.com/rsuite/rsuite-table/issues/158)

Table ref

PropertyTypeDescription
bodyHTMLDivElementThe body element of the table
rootHTMLDivElementThe root element of the table
scrollLeft(left:number)=>voidSet the number of pixels for horizontal scrolling of the table
scrollPosition{top:number,left:number}The scroll position of the table
scrollTop(top:number)=>voidSet the number of pixels for vertical scrolling of the table

Type safety

We can pass generic type parameters to Table, Cell etc. for better type-safety when using typescript.

Passing a render prop to Table is recommended when using TS, as this will ensure that the right generic type parameter is automatically propagated to the Cell component.

const products: Product[] = [{ name: 'Pineapple' }];

<Table<Product, string> ref={table} data={products}>
  {({ Column, HeaderCell, Cell }) => (
    <>
      <Column>
        <HeaderCell>Name</HeaderCell>
        {/* No need for passing explicit type parameter to Cell */}
        <Cell>{row => row.name}</Cell>
      </Column>
    </>
  )}
</Table>;

In fact, the type parameter from table can be inferred from the data passed to it, so the type parameter to Table can also be skipped.

const products: Product[] = [{ name: 'Pineapple' }];

<Table data={products}>
  {({ Column, HeaderCell, Cell }) => (
    <>
      <Column>
        <HeaderCell>Name</HeaderCell>
        <Cell>{row => row.name}</Cell>
      </Column>
    </>
  )}
</Table>;

When writing reusable components, it is recommended to make your components generic as well. For example:

interface ImageCellProps<TKey extends string, TRow extends Record<TKey, string>> {
  rowData: TRow;
  dataKey: TKey;
  // ... any other props
}

const ImageCell = <TKey extends string, TRow extends Record<TKey, string>>({
  rowData,
  dataKey,
  ...rest
}: ImageCellProps<TKey, TRow>) => (
  <Cell<TRow, TKey> {...rest}>
    <img src={rowData[dataKey]} width="50" />
  </Cell>
);