Hooks for building lightweight, fast and extendable datagrids for React
—
React Table provides a comprehensive set of utility functions, constants, and helper components that support table functionality and enable advanced customizations.
Built-in constants and default configurations used throughout React Table.
/** Action type constants registry */
const actions: ActionTypes;
/** Default cell renderer that displays the cell value */
const defaultRenderer: ({ value }: { value: any }) => any;
/** Empty cell renderer that displays non-breaking space */
const emptyRenderer: () => React.ReactElement;
/** Default column configuration object */
const defaultColumn: Column;Usage Example:
import { actions, defaultRenderer, defaultColumn } from 'react-table';
// Using actions in custom reducers
const customReducer = (state, action) => {
if (action.type === actions.resetFilters) {
// Custom reset logic
return { ...state, customFilters: [] };
}
return state;
};
// Using default column config
const columns = [
{
Header: 'Name',
accessor: 'name',
Cell: defaultRenderer, // Explicit use of default renderer
},
{
Header: 'Actions',
id: 'actions',
Cell: () => <button>Edit</button>,
},
];
// Custom default column configuration
const customDefaultColumn = {
...defaultColumn,
Cell: ({ value }) => value || '-', // Custom default for empty values
Filter: ({ column: { filterValue, setFilter } }) => (
<input
value={filterValue || ''}
onChange={e => setFilter(e.target.value)}
/>
),
};Flexible rendering utilities for components and dynamic content.
/**
* Flexible component renderer that handles various component types
* @param component - Component, element, string, or function to render
* @param props - Props to pass to the component
* @returns Rendered React element
*/
function flexRender(
component: Renderer,
props: any
): React.ReactElement;
/**
* Creates a renderer function from a component
* @param component - Component to wrap
* @returns Renderer function
*/
function makeRenderer(component: Renderer): Function;
type Renderer =
| React.ComponentType<any>
| React.ReactElement
| string
| ((props: any) => React.ReactElement);Usage Example:
import { flexRender, makeRenderer } from 'react-table';
// Custom cell with dynamic rendering
const DynamicCell = ({ cell }) => {
const { value, column } = cell;
// Different renderers based on column type
const renderer = column.cellType === 'button'
? ({ value }) => <button>{value}</button>
: column.cellType === 'link'
? ({ value }) => <a href={value}>{value}</a>
: ({ value }) => <span>{value}</span>;
return flexRender(renderer, { value });
};
// Using makeRenderer for consistent component wrapping
const StatusRenderer = makeRenderer(({ value }) => {
const className = `status-${value.toLowerCase()}`;
return <span className={className}>{value}</span>;
});
const columns = [
{
Header: 'Status',
accessor: 'status',
Cell: StatusRenderer,
},
];Utilities for creating and managing prop getter functions.
/**
* Creates a prop getter function that merges props from hooks and user input
* @param hooks - Array of hook functions that return props
* @param meta - Metadata passed to hooks
* @returns Prop getter function
*/
function makePropGetter(
hooks: Array<(props: any, meta: any) => any>,
meta?: any
): PropGetter;
type PropGetter = (userProps?: any) => object;Usage Example:
import { makePropGetter } from 'react-table';
// Custom prop getter for special row styling
const createRowPropGetter = (hooks, meta) => {
const baseGetRowProps = makePropGetter(hooks, meta);
return (userProps = {}) => {
const props = baseGetRowProps(userProps);
// Add custom row styling based on row data
if (meta.row.original.status === 'error') {
props.className = `${props.className || ''} error-row`.trim();
props.style = {
...props.style,
backgroundColor: '#ffebee',
};
}
return props;
};
};Utilities for processing and executing hook functions.
/**
* Executes reducer-type hooks in sequence
* @param hooks - Array of reducer hooks
* @param initial - Initial value
* @param meta - Metadata passed to hooks
* @param allowUndefined - Whether to allow undefined return values
* @returns Final reduced value
*/
function reduceHooks(
hooks: Array<(prev: any, meta: any) => any>,
initial: any,
meta?: any,
allowUndefined?: boolean
): any;
/**
* Executes side-effect hooks (hooks that don't return values)
* @param hooks - Array of side-effect hooks
* @param context - Context object passed to hooks
* @param meta - Metadata passed to hooks
*/
function loopHooks(
hooks: Array<(context: any, meta: any) => void>,
context: any,
meta?: any
): void;
/**
* Ensures plugins are in the correct order based on dependencies
* @param plugins - Array of plugin functions
* @param befores - Array of plugin names that must come before
* @param pluginName - Name of the current plugin
*/
function ensurePluginOrder(
plugins: PluginHook[],
befores: string[],
pluginName: string
): void;Usage Example:
import { reduceHooks, loopHooks, ensurePluginOrder } from 'react-table';
// Custom plugin that depends on other plugins
function useCustomPlugin(hooks) {
// Ensure this plugin comes after useSortBy
ensurePluginOrder(hooks.plugins, ['useSortBy'], 'useCustomPlugin');
hooks.useInstance.push((instance) => {
// Add custom instance methods
Object.assign(instance, {
customMethod: () => {
console.log('Custom method called');
},
});
});
hooks.stateReducers.push((newState, action, previousState, instance) => {
if (action.type === 'customAction') {
return {
...newState,
customState: action.payload,
};
}
return newState;
});
}
useCustomPlugin.pluginName = 'useCustomPlugin';Specialized React hooks for table functionality.
/**
* Gets the latest value reference to prevent stale closures
* @param obj - Object to get latest reference for
* @returns Function that returns the latest value
*/
function useGetLatest<T>(obj: T): () => T;
/**
* Cross-platform layout effect (useLayoutEffect in browser, useEffect in SSR)
*/
const safeUseLayoutEffect: typeof React.useLayoutEffect;
/**
* Layout effect that only runs when component is mounted
* @param effect - Effect function
* @param deps - Dependency array
*/
function useMountedLayoutEffect(
effect: React.EffectCallback,
deps?: React.DependencyList
): void;
/**
* Creates an async debounced function
* @param fn - Function to debounce
* @param wait - Debounce delay in milliseconds
* @returns Debounced function
*/
function useAsyncDebounce<T extends (...args: any[]) => any>(
fn: T,
wait: number
): T;Usage Example:
import {
useGetLatest,
useMountedLayoutEffect,
useAsyncDebounce,
} from 'react-table';
function CustomTableComponent({ data, onDataChange }) {
const [localData, setLocalData] = React.useState(data);
// Prevent stale closure issues
const getLatestData = useGetLatest(localData);
// Debounced save function
const debouncedSave = useAsyncDebounce(async (newData) => {
await onDataChange(newData);
}, 1000);
// Effect that only runs when mounted
useMountedLayoutEffect(() => {
const currentData = getLatestData();
if (currentData !== data) {
debouncedSave(currentData);
}
}, [localData]);
return (
<div>
{/* Table implementation */}
</div>
);
}Utilities for handling state updates and functional updates.
/**
* Handles functional updates (updater functions or direct values)
* @param updater - Update function or direct value
* @param old - Previous value
* @returns New value
*/
function functionalUpdate<T>(
updater: T | ((old: T) => T),
old: T
): T;Usage Example:
import { functionalUpdate } from 'react-table';
// Custom state management with functional updates
function useCustomTableState(initialState) {
const [state, setState] = React.useState(initialState);
const updateState = React.useCallback((updater) => {
setState(prevState => functionalUpdate(updater, prevState));
}, []);
return [state, updateState];
}
// Usage
function MyTable() {
const [tableState, setTableState] = useCustomTableState({
filters: [],
sortBy: [],
});
// Direct value update
const clearFilters = () => {
setTableState({ ...tableState, filters: [] });
};
// Functional update
const addFilter = (filter) => {
setTableState(prevState => ({
...prevState,
filters: [...prevState.filters, filter],
}));
};
return (
<div>
{/* Table implementation */}
</div>
);
}Built-in aggregation functions for grouped data.
interface AggregationFunctions {
/** Sum of numeric values */
sum: (leafValues: any[]) => number;
/** Minimum value */
min: (leafValues: any[]) => any;
/** Maximum value */
max: (leafValues: any[]) => any;
/** Min-max range as string */
minMax: (leafValues: any[]) => string;
/** Average of values */
average: (leafValues: any[]) => number;
/** Median value */
median: (leafValues: any[]) => number;
/** Array of unique values */
unique: (leafValues: any[]) => any[];
/** Count of unique values */
uniqueCount: (leafValues: any[]) => number;
/** Total count */
count: (leafValues: any[]) => number;
}Usage Example:
import { useTable, useGroupBy } from 'react-table';
function GroupedTable({ columns, data }) {
const aggregationColumns = React.useMemo(() => [
...columns,
{
Header: 'Summary',
columns: [
{
Header: 'Total Sales',
accessor: 'sales',
aggregate: 'sum',
Aggregated: ({ value }) => `$${value.toLocaleString()}`,
},
{
Header: 'Avg Rating',
accessor: 'rating',
aggregate: 'average',
Aggregated: ({ value }) => Math.round(value * 100) / 100,
},
{
Header: 'Count',
accessor: 'id',
aggregate: 'count',
Aggregated: ({ value }) => `${value} items`,
},
],
},
], [columns]);
const tableInstance = useTable(
{
columns: aggregationColumns,
data,
},
useGroupBy
);
// Table implementation...
}Patterns for creating custom utilities that integrate with React Table.
// Custom utility for table data export
function createExportUtility(tableInstance) {
const exportToCSV = () => {
const { flatHeaders, rows } = tableInstance;
// Create CSV header
const header = flatHeaders
.filter(header => header.isVisible)
.map(header => header.Header)
.join(',');
// Create CSV rows
const csvRows = rows.map(row => {
return flatHeaders
.filter(header => header.isVisible)
.map(header => {
const cell = row.cells.find(cell => cell.column.id === header.id);
return JSON.stringify(cell?.value || '');
})
.join(',');
});
// Combine and download
const csvContent = [header, ...csvRows].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'table-data.csv';
link.click();
URL.revokeObjectURL(url);
};
return { exportToCSV };
}
// Usage
function ExportableTable({ columns, data }) {
const tableInstance = useTable({ columns, data });
const { exportToCSV } = createExportUtility(tableInstance);
return (
<div>
<button onClick={exportToCSV}>
Export to CSV
</button>
{/* Table implementation */}
</div>
);
}interface ActionTypes {
init: string;
resetFilters: string;
setFilter: string;
setAllFilters: string;
resetSortBy: string;
setSortBy: string;
toggleSortBy: string;
resetGlobalFilter: string;
setGlobalFilter: string;
resetPage: string;
gotoPage: string;
setPageSize: string;
toggleAllRowsSelected: string;
toggleRowSelected: string;
toggleAllRowsExpanded: string;
toggleRowExpanded: string;
setColumnOrder: string;
resetSelectedRows: string;
resetExpanded: string;
resetGroupBy: string;
setGroupBy: string;
toggleGroupBy: string;
resetRowState: string;
setCellState: string;
resetPivot: string;
togglePivot: string;
}
interface UtilityMeta {
instance: TableInstance;
column?: Column;
row?: Row;
cell?: Cell;
}Install with Tessl CLI
npx tessl i tessl/npm-react-table