Hooks for building lightweight, fast and extendable datagrids for React
—
The core table functionality provides the foundation for all React Table features. Every table implementation starts with the useTable hook and its required configuration.
The primary hook that creates and manages the table instance. This is the foundation hook that must be used for all table functionality.
/**
* Creates a table instance with the provided data and columns
* @param props - Table configuration options
* @param plugins - Plugin hooks to extend functionality
* @returns Table instance with state, methods, and computed values
*/
function useTable(
props: TableOptions,
...plugins: PluginHook[]
): TableInstance;
interface TableOptions {
/** Array of data objects to display in the table */
data: any[];
/** Array of column definitions */
columns: Column[];
/** Initial table state */
initialState?: Partial<TableState>;
/** Default column configuration that applies to all columns */
defaultColumn?: Partial<Column>;
/** Function to extract sub-rows from a row (for nested data) */
getSubRows?: (row: any, index: number) => any[];
/** Function to generate unique row IDs */
getRowId?: (row: any, index: number, parent?: Row) => string;
/** Custom state reducer for controlling state updates */
stateReducer?: (
newState: TableState,
action: ActionType,
previousState: TableState
) => TableState;
/** Hook to control the final state after all reducers */
useControlledState?: (state: TableState) => TableState;
}
interface TableInstance {
// State Management
state: TableState;
dispatch: (action: ActionType) => void;
// Column Information
columns: Column[];
allColumns: Column[];
visibleColumns: Column[];
headerGroups: HeaderGroup[];
footerGroups: HeaderGroup[];
headers: Header[];
flatHeaders: Header[];
// Row Information
rows: Row[];
flatRows: Row[];
rowsById: Record<string, Row>;
// Core Methods
prepareRow: (row: Row) => void;
getTableProps: PropGetter;
getTableBodyProps: PropGetter;
}Usage Example:
import React from 'react';
import { useTable } from 'react-table';
function BasicTable() {
const data = React.useMemo(() => [
{ id: 1, name: 'John', age: 30 },
{ id: 2, name: 'Jane', age: 25 },
], []);
const columns = React.useMemo(() => [
{
Header: 'Name',
accessor: 'name',
},
{
Header: 'Age',
accessor: 'age',
},
], []);
const tableInstance = useTable({
columns,
data,
});
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = tableInstance;
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => (
<td {...cell.getCellProps()}>
{cell.render('Cell')}
</td>
))}
</tr>
);
})}
</tbody>
</table>
);
}Columns define how data is accessed, displayed, and behave in the table.
interface Column {
/** Column header content (component, string, or render function) */
Header?: Renderer;
/** Column footer content */
Footer?: Renderer;
/** Cell renderer (defaults to displaying the value) */
Cell?: Renderer;
/** Data accessor - string key or function to extract cell value */
accessor?: string | ((row: any, index: number) => any);
/** Unique column identifier (auto-generated if not provided) */
id?: string;
/** Column width in pixels */
width?: number;
/** Minimum column width */
minWidth?: number;
/** Maximum column width */
maxWidth?: number;
/** Whether this column can be sorted */
disableSortBy?: boolean;
/** Whether this column can be filtered */
disableFilters?: boolean;
/** Whether this column can be grouped */
disableGroupBy?: boolean;
/** Whether this column is visible */
show?: boolean;
}
interface HeaderGroup {
headers: Header[];
getHeaderGroupProps: PropGetter;
}
interface Header {
id: string;
column: Column;
Header: Renderer;
getHeaderProps: PropGetter;
render: (type: string) => React.ReactElement;
}Column Definition Examples:
const columns = [
// Simple string accessor
{
Header: 'First Name',
accessor: 'firstName',
},
// Function accessor for computed values
{
Header: 'Full Name',
id: 'fullName',
accessor: row => `${row.firstName} ${row.lastName}`,
},
// Custom cell renderer
{
Header: 'Status',
accessor: 'status',
Cell: ({ value }) => (
<span className={`status-${value}`}>
{value}
</span>
),
},
// Column with width constraints
{
Header: 'Actions',
id: 'actions',
width: 100,
minWidth: 100,
maxWidth: 100,
Cell: ({ row }) => (
<button onClick={() => handleEdit(row.original)}>
Edit
</button>
),
},
];Rows and cells provide structured access to data and rendering utilities.
interface Row {
/** Unique row identifier */
id: string;
/** Row index in the data array */
index: number;
/** Original data object for this row */
original: any;
/** Array of cell objects for this row */
cells: Cell[];
/** Object containing all computed column values */
values: Record<string, any>;
/** Sub-rows (for hierarchical data) */
subRows?: Row[];
/** Get props for the row element */
getRowProps: PropGetter;
}
interface Cell {
/** Column definition for this cell */
column: Column;
/** Row containing this cell */
row: Row;
/** Computed value for this cell */
value: any;
/** Get props for the cell element */
getCellProps: PropGetter;
/** Render the cell content */
render: (type: string) => React.ReactElement;
}Prop getters provide HTML attributes and event handlers for table elements.
type PropGetter = (props?: any) => object;
interface PropGetterMethods {
/** Get props for the table element */
getTableProps: PropGetter;
/** Get props for the table body element */
getTableBodyProps: PropGetter;
/** Get props for header group rows */
getHeaderGroupProps: PropGetter;
/** Get props for individual headers */
getHeaderProps: PropGetter;
/** Get props for table rows */
getRowProps: PropGetter;
/** Get props for table cells */
getCellProps: PropGetter;
}Prop Getter Usage:
// Basic usage
<table {...getTableProps()}>
<tbody {...getTableBodyProps()}>
{rows.map(row => (
<tr {...row.getRowProps()}>
{row.cells.map(cell => (
<td {...cell.getCellProps()}>
{cell.render('Cell')}
</td>
))}
</tr>
))}
</tbody>
</table>
// Adding custom props
<table {...getTableProps({ className: 'my-table' })}>
<tr {...row.getRowProps({
onClick: () => handleRowClick(row),
className: row.isSelected ? 'selected' : ''
})}>
{/* cells */}
</tr>
</table>React Table manages internal state but allows for external control and customization.
interface TableState {
/** Current page index (with usePagination) */
pageIndex?: number;
/** Current page size (with usePagination) */
pageSize?: number;
/** Current sort configuration (with useSortBy) */
sortBy?: SortingRule[];
/** Column filter values (with useFilters) */
filters?: Filter[];
/** Global filter value (with useGlobalFilter) */
globalFilter?: any;
/** Column visibility (with useColumnVisibility) */
hiddenColumns?: string[];
/** Selected row IDs (with useRowSelect) */
selectedRowIds?: Record<string, boolean>;
/** Expanded row IDs (with useExpanded) */
expanded?: Record<string, boolean>;
/** Column order (with useColumnOrder) */
columnOrder?: string[];
/** Row state by row ID (with useRowState) */
rowState?: Record<string, any>;
}
interface ActionType {
type: string;
[key: string]: any;
}State Control Example:
// Controlled state
const [tableState, setTableState] = React.useState({
pageIndex: 0,
pageSize: 10,
});
const tableInstance = useTable(
{
columns,
data,
initialState: tableState,
// Control state updates
stateReducer: (newState, action) => {
setTableState(newState);
return newState;
},
},
usePagination
);Before rendering rows, you must call prepareRow for each row to ensure proper initialization.
/**
* Prepares a row for rendering by initializing its cells and properties
* @param row - The row to prepare
*/
prepareRow: (row: Row) => void;Critical Usage Pattern:
// REQUIRED: Call prepareRow before rendering
{rows.map(row => {
prepareRow(row); // This must be called!
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => (
<td {...cell.getCellProps()}>
{cell.render('Cell')}
</td>
))}
</tr>
);
})}type Renderer =
| React.ComponentType<any>
| React.ReactElement
| string
| ((props: any) => React.ReactElement);
interface PluginHook {
(hooks: Hooks): void;
pluginName?: string;
}
interface Hooks {
columns: Array<(columns: Column[], meta: any) => Column[]>;
allColumns: Array<(columns: Column[], meta: any) => Column[]>;
visibleColumns: Array<(columns: Column[], meta: any) => Column[]>;
headerGroups: Array<(headerGroups: HeaderGroup[], meta: any) => HeaderGroup[]>;
useOptions: Array<(options: any, meta: any) => any>;
stateReducers: Array<(state: any, action: any, prevState: any, instance: any) => any>;
useControlledState: Array<(state: any, meta: any) => any>;
useInstanceAfterData: Array<(instance: any) => void>;
}Install with Tessl CLI
npx tessl i tessl/npm-react-table