Component API
Use this page when you already know which capability you want and need the exact top-level prop or export surface. For implementation guidance, start with the rewritten guides and concepts pages.
Public imports
import {
Datatable,
DataTableProvider,
useDatatableColumns,
useDatatableColumnSizing,
useDatatableStore,
useDatatableStoreApi,
type DatatableColumn,
type DatatableProps,
} from "./react-datatable"Datatableis the component export.DatatablePropsis the component prop type.DataTableProviderand store hooks are lower-level exports for advanced integrations around the shipped table state model.
Main component contract
interface DatatableProps<TData> {
tableKey: string
columns: DatatableColumn<TData>[]
getRowId?: (row: TData) => string
initialState?: Partial<DatatableState>
runtimeRestoration?: boolean | { key?: string; pagination?: boolean; scroll?: boolean }
onReadyStateChange?: (ready: boolean) => void
rowHeight?: number
headerHeight?: number
virtualization?: DataTableVirtualizationConfig
columnReordering?: DataTableColumnReorderingConfig
selection?: DataTableRowSelectionConfig<TData>
bulkActions?: DataTableBulkActionsConfig<TData>
rowPresentation?: DataTableRowPresentationConfig<TData>
keyboardNavigation?: DataTableKeyboardNavigationConfig
rowActions?: DataTableRowActionsConfig<TData>
preview?: DataTableRowPreviewConfig<TData>
enableColumnResizing?: boolean
columnResizeMode?: "onChange" | "onEnd"
persistState?: { ... }
urlSync?: boolean | Omit<UseDatatableUrlOptions<TData>, "columns">
stickyColumnsCount?: number
columnVisibilityUI?: ColumnVisibilityUIConfig
displayOptions?: boolean | DataTableDisplayOptionsConfig
views?: { ... }
toolbar?: boolean | { ... }
viewColumnsButton?: boolean | { ... }
debug?: boolean
}
type DatatableLocalModeProps<TData> = {
data: TData[]
online?: never
}
type DatatableOnlineModeProps<TData> = {
online: OnlineConfig<TData>
data?: never
}Required setup
tableKey
tableKey is required. Use a stable product-surface key such as "customers", "deals", or "workspace-members". The table uses it as the default key for runtime restoration, persistence, saved views, and floating preview position.
columns
columns is required. The table uses this model for rendering, sorting, filtering, grouping, visibility, and customization seams.
See Column API for the full column shape.
data or online
Provide exactly one primary data mode:
data: local/offline mode. The table owns filtering, sorting, grouping, and viewport rendering against the array you pass in.online: server-driven mode. The table owns interaction state, but your query function owns row retrieval, totals, facets, and backend ordering.
If the first online response is already loaded by a route loader or parent cache, pass it through online.initialData. Top-level data is only for local mode.
If you provide neither, the component throws during render.
See:
getRowId
Use getRowId when your row key is not the default TanStack row index. In practice you should provide it for any real product table so selection, preview, persistence, and online transitions stay stable.
Initialization and readiness
initialState
<Datatable
tableKey="customers"
initialState={{
sorting: [{ id: "updatedAt", desc: true }],
globalFilter: "active",
grouping: ["status"],
}}
/>initialState seeds the store before saved views, persisted state, and URL state are merged in. Treat it as your developer default, not as a forced final state.
See State Lifecycle.
onReadyStateChange
onReadyStateChange(ready) fires when the table has finished loading coordinated state sources and the interactive surface is ready.
Use it when surrounding UI must wait for:
- persisted current-view state
- default saved views
- initial URL state
- initial online loading
runtimeRestoration
Runtime restoration keeps navigation position available while the current browser session is alive. It is useful in SPAs where a table can unmount and remount as users switch tabs, open a row detail route, or move between sibling screens.
It is enabled by default and uses the top-level tableKey.
<Datatable
tableKey="customers"
runtimeRestoration={{
pagination: true,
scroll: true,
}}
/>The available shape is:
boolean | {
key?: string
pagination?: boolean
scroll?: boolean
}Use runtimeRestoration={false} when route changes should always return the table to its initial runtime position. Use { pagination: false } when page movement should reset on remount but scroll should still come back, or { scroll: false } when page state should return but scroll should start at the top.
This is separate from persistState. Runtime pagination and scroll position use sessionStorage by default so they survive remounts and hard refreshes in the same browser tab. Persisted state is durable user preference storage.
Sizing and layout
rowHeight
Height of data rows.
- default:
40
headerHeight
Height of header rows.
- default:
40
stickyColumnsCount
Initial number of left-frozen columns. Users can still change frozen columns later if you expose the relevant display options controls.
enableColumnResizing
Enables header drag resizing.
- default:
true
columnResizeMode
"onChange" | "onEnd"onChange: resize continuously while draggingonEnd: update width after drag ends
Feature configuration groups
The top-level API is intentionally grouped by reader job. Most capabilities live under one focused prop object.
<Datatable
tableKey="customers"
virtualization={{ ... }}
columnReordering={{ ... }}
selection={{ ... }}
bulkActions={{ ... }}
rowPresentation={{ ... }}
keyboardNavigation={{ ... }}
rowActions={{ ... }}
preview={{ ... }}
persistState={{ ... }}
urlSync={{ ... }}
views={{ ... }}
toolbar={{ ... }}
displayOptions={{ ... }}
viewColumnsButton={{ ... }}
/>virtualization
Controls viewport rendering policy and overscan.
{
mode?: "viewport" | "full"
rowOverscanCount?: number
columnOverscanCount?: number
}Use this for render-cost tuning, not data fetching.
See Tune virtualization.
columnReordering
Controls drag behavior for visible columns.
{
allowFrozenBoundaryCrossing?: boolean
widthMorph?: "none" | "snap" | "interpolate"
}See Add column ordering.
selection
Enables row selection.
{
enabled: boolean
mode?: "multi"
showCheckboxOnHover?: boolean
maxSelectedRows?: number
allowSelectAllMatching?: boolean
getRowCanSelect?: (row) => boolean
}See Add row selection.
bulkActions
Configures the selected-row action flow.
{
actions: DataTableBulkAction<TData>[]
triggerLabel?: string
serverExecutor?: (request: DataTableBulkServerActionRequest) => void | Promise<void>
}See Add bulk actions.
rowPresentation
Adds state-aware row and cell styling hooks.
Use it when selection, active-row, or preview state should change classes or attributes without replacing the underlying table behavior.
keyboardNavigation
{
enabled?: boolean
autoFocus?: boolean
}Enables active-row keyboard movement and related Enter/Space behavior.
rowActions
{
onOpenRow?: (context) => void | Promise<void>
onTogglePreviewRow?: (context) => void | Promise<void>
}Use rowActions when the table should signal row intent but your app owns the actual route navigation or domain-specific side effect.
preview
{
enabled?: boolean
floating?: {
draggable?: boolean
storageKey?: string
}
renderPreview: ({ row, rowId, close }) => ReactNode
}Adds the built-in preview surface for the current preview row.
See:
Persistence, sharing, and URL state
persistState
Use persistState for the current user's remembered table state.
<Datatable
tableKey="customers"
persistState={{
adapter: localStorageAdapter,
workspaceId: "wsp_123",
userId: "usr_456",
debounceMs: 1000,
onSave: () => {},
onError: (error) => console.error(error),
}}
/>Required fields:
adapter
Optional fields:
tableKeywhen this adapter should use a namespace different from the top-level table keyworkspaceIduserIddebounceMsonSaveonError
See Add current-view persistence.
urlSync
boolean | {
enabled?: boolean
acceptUrlParams?: boolean
historyMode?: "push" | "replace"
...
}false: do not write ongoing state to the URL, but still accept incoming URL params by defaulttrue: enable continuous bidirectional URL synchronization- object: configure the URL behavior explicitly
Only one table per page should actively write to the shared query param space.
See Add URL sync.
views
Use views for named saved views.
<Datatable
tableKey="customers"
views={{
adapter,
workspaceId: "wsp_123",
userId: "usr_456",
enableWorkspaceSharing: true,
enableUserDefaults: true,
onSuccess: () => {},
onError: (error) => console.error(error),
}}
toolbar={{ views: true }}
/>Required fields:
adapter
Optional fields:
tableKeywhen this adapter should use a namespace different from the top-level table keyworkspaceIduserIdenableWorkspaceSharingenableUserDefaultsonSuccessonError
If views is configured but toolbar.views is hidden, the saved-view data model still exists but the shipped toolbar entry point does not render.
See:
Toolbar and display surfaces
toolbar
boolean | {
quickSearch?: boolean | {
placeholder?: string
debounceMs?: number
}
filterButton?: boolean
displayOptions?: boolean
copyLink?: boolean
views?: boolean
appliedState?: {
showSorting?: boolean
showFilters?: boolean
}
}Use this to choose which shipped toolbar controls appear. It does not replace the underlying feature contracts; it exposes or hides the surface.
See:
displayOptions
boolean | {
sections?: {
grouping?: boolean
ordering?: boolean
freezeColumns?: boolean
displaySettings?: boolean
columnVisibility?: boolean
}
controls?: {
showEmptyGroups?: boolean
showOrderingBadge?: boolean
}
}false hides the display options button completely. An object keeps the button but limits what users can control.
columnVisibilityUI
Controls how column visibility management renders.
badgesdropdownauto
viewColumnsButton
boolean | {
show?: boolean
width?: number
}Controls the optional right-side view-columns affordance.
Lower-level exports
DataTableProvider
Creates the isolated store and coordinates initialState, persistence, saved views, and URL state before the table body renders.
Use it only when you are building a more custom wrapper around the shipped table internals.
useDatatableColumns
Returns column metadata from provider context for internal-style integrations that need the current public column model.
useDatatableColumnSizing
Lower-level sizing hook exported from DataTableBody.
useDatatableStore and useDatatableStoreApi
Advanced hooks into the Zustand-backed table store.
Reach for these only when prop-level APIs are not enough and you are intentionally extending the source-owned table behavior.