0
# Utilities and Helpers
1
2
React Table provides a comprehensive set of utility functions, constants, and helper components that support table functionality and enable advanced customizations.
3
4
## Capabilities
5
6
### Core Constants and Defaults
7
8
Built-in constants and default configurations used throughout React Table.
9
10
```javascript { .api }
11
/** Action type constants registry */
12
const actions: ActionTypes;
13
14
/** Default cell renderer that displays the cell value */
15
const defaultRenderer: ({ value }: { value: any }) => any;
16
17
/** Empty cell renderer that displays non-breaking space */
18
const emptyRenderer: () => React.ReactElement;
19
20
/** Default column configuration object */
21
const defaultColumn: Column;
22
```
23
24
**Usage Example:**
25
26
```javascript
27
import { actions, defaultRenderer, defaultColumn } from 'react-table';
28
29
// Using actions in custom reducers
30
const customReducer = (state, action) => {
31
if (action.type === actions.resetFilters) {
32
// Custom reset logic
33
return { ...state, customFilters: [] };
34
}
35
return state;
36
};
37
38
// Using default column config
39
const columns = [
40
{
41
Header: 'Name',
42
accessor: 'name',
43
Cell: defaultRenderer, // Explicit use of default renderer
44
},
45
{
46
Header: 'Actions',
47
id: 'actions',
48
Cell: () => <button>Edit</button>,
49
},
50
];
51
52
// Custom default column configuration
53
const customDefaultColumn = {
54
...defaultColumn,
55
Cell: ({ value }) => value || '-', // Custom default for empty values
56
Filter: ({ column: { filterValue, setFilter } }) => (
57
<input
58
value={filterValue || ''}
59
onChange={e => setFilter(e.target.value)}
60
/>
61
),
62
};
63
```
64
65
### Rendering Utilities
66
67
Flexible rendering utilities for components and dynamic content.
68
69
```javascript { .api }
70
/**
71
* Flexible component renderer that handles various component types
72
* @param component - Component, element, string, or function to render
73
* @param props - Props to pass to the component
74
* @returns Rendered React element
75
*/
76
function flexRender(
77
component: Renderer,
78
props: any
79
): React.ReactElement;
80
81
/**
82
* Creates a renderer function from a component
83
* @param component - Component to wrap
84
* @returns Renderer function
85
*/
86
function makeRenderer(component: Renderer): Function;
87
88
type Renderer =
89
| React.ComponentType<any>
90
| React.ReactElement
91
| string
92
| ((props: any) => React.ReactElement);
93
```
94
95
**Usage Example:**
96
97
```javascript
98
import { flexRender, makeRenderer } from 'react-table';
99
100
// Custom cell with dynamic rendering
101
const DynamicCell = ({ cell }) => {
102
const { value, column } = cell;
103
104
// Different renderers based on column type
105
const renderer = column.cellType === 'button'
106
? ({ value }) => <button>{value}</button>
107
: column.cellType === 'link'
108
? ({ value }) => <a href={value}>{value}</a>
109
: ({ value }) => <span>{value}</span>;
110
111
return flexRender(renderer, { value });
112
};
113
114
// Using makeRenderer for consistent component wrapping
115
const StatusRenderer = makeRenderer(({ value }) => {
116
const className = `status-${value.toLowerCase()}`;
117
return <span className={className}>{value}</span>;
118
});
119
120
const columns = [
121
{
122
Header: 'Status',
123
accessor: 'status',
124
Cell: StatusRenderer,
125
},
126
];
127
```
128
129
### Prop Getter Utilities
130
131
Utilities for creating and managing prop getter functions.
132
133
```javascript { .api }
134
/**
135
* Creates a prop getter function that merges props from hooks and user input
136
* @param hooks - Array of hook functions that return props
137
* @param meta - Metadata passed to hooks
138
* @returns Prop getter function
139
*/
140
function makePropGetter(
141
hooks: Array<(props: any, meta: any) => any>,
142
meta?: any
143
): PropGetter;
144
145
type PropGetter = (userProps?: any) => object;
146
```
147
148
**Usage Example:**
149
150
```javascript
151
import { makePropGetter } from 'react-table';
152
153
// Custom prop getter for special row styling
154
const createRowPropGetter = (hooks, meta) => {
155
const baseGetRowProps = makePropGetter(hooks, meta);
156
157
return (userProps = {}) => {
158
const props = baseGetRowProps(userProps);
159
160
// Add custom row styling based on row data
161
if (meta.row.original.status === 'error') {
162
props.className = `${props.className || ''} error-row`.trim();
163
props.style = {
164
...props.style,
165
backgroundColor: '#ffebee',
166
};
167
}
168
169
return props;
170
};
171
};
172
```
173
174
### Hook Utilities
175
176
Utilities for processing and executing hook functions.
177
178
```javascript { .api }
179
/**
180
* Executes reducer-type hooks in sequence
181
* @param hooks - Array of reducer hooks
182
* @param initial - Initial value
183
* @param meta - Metadata passed to hooks
184
* @param allowUndefined - Whether to allow undefined return values
185
* @returns Final reduced value
186
*/
187
function reduceHooks(
188
hooks: Array<(prev: any, meta: any) => any>,
189
initial: any,
190
meta?: any,
191
allowUndefined?: boolean
192
): any;
193
194
/**
195
* Executes side-effect hooks (hooks that don't return values)
196
* @param hooks - Array of side-effect hooks
197
* @param context - Context object passed to hooks
198
* @param meta - Metadata passed to hooks
199
*/
200
function loopHooks(
201
hooks: Array<(context: any, meta: any) => void>,
202
context: any,
203
meta?: any
204
): void;
205
206
/**
207
* Ensures plugins are in the correct order based on dependencies
208
* @param plugins - Array of plugin functions
209
* @param befores - Array of plugin names that must come before
210
* @param pluginName - Name of the current plugin
211
*/
212
function ensurePluginOrder(
213
plugins: PluginHook[],
214
befores: string[],
215
pluginName: string
216
): void;
217
```
218
219
**Usage Example:**
220
221
```javascript
222
import { reduceHooks, loopHooks, ensurePluginOrder } from 'react-table';
223
224
// Custom plugin that depends on other plugins
225
function useCustomPlugin(hooks) {
226
// Ensure this plugin comes after useSortBy
227
ensurePluginOrder(hooks.plugins, ['useSortBy'], 'useCustomPlugin');
228
229
hooks.useInstance.push((instance) => {
230
// Add custom instance methods
231
Object.assign(instance, {
232
customMethod: () => {
233
console.log('Custom method called');
234
},
235
});
236
});
237
238
hooks.stateReducers.push((newState, action, previousState, instance) => {
239
if (action.type === 'customAction') {
240
return {
241
...newState,
242
customState: action.payload,
243
};
244
}
245
return newState;
246
});
247
}
248
249
useCustomPlugin.pluginName = 'useCustomPlugin';
250
```
251
252
### React Hook Utilities
253
254
Specialized React hooks for table functionality.
255
256
```javascript { .api }
257
/**
258
* Gets the latest value reference to prevent stale closures
259
* @param obj - Object to get latest reference for
260
* @returns Function that returns the latest value
261
*/
262
function useGetLatest<T>(obj: T): () => T;
263
264
/**
265
* Cross-platform layout effect (useLayoutEffect in browser, useEffect in SSR)
266
*/
267
const safeUseLayoutEffect: typeof React.useLayoutEffect;
268
269
/**
270
* Layout effect that only runs when component is mounted
271
* @param effect - Effect function
272
* @param deps - Dependency array
273
*/
274
function useMountedLayoutEffect(
275
effect: React.EffectCallback,
276
deps?: React.DependencyList
277
): void;
278
279
/**
280
* Creates an async debounced function
281
* @param fn - Function to debounce
282
* @param wait - Debounce delay in milliseconds
283
* @returns Debounced function
284
*/
285
function useAsyncDebounce<T extends (...args: any[]) => any>(
286
fn: T,
287
wait: number
288
): T;
289
```
290
291
**Usage Example:**
292
293
```javascript
294
import {
295
useGetLatest,
296
useMountedLayoutEffect,
297
useAsyncDebounce,
298
} from 'react-table';
299
300
function CustomTableComponent({ data, onDataChange }) {
301
const [localData, setLocalData] = React.useState(data);
302
303
// Prevent stale closure issues
304
const getLatestData = useGetLatest(localData);
305
306
// Debounced save function
307
const debouncedSave = useAsyncDebounce(async (newData) => {
308
await onDataChange(newData);
309
}, 1000);
310
311
// Effect that only runs when mounted
312
useMountedLayoutEffect(() => {
313
const currentData = getLatestData();
314
if (currentData !== data) {
315
debouncedSave(currentData);
316
}
317
}, [localData]);
318
319
return (
320
<div>
321
{/* Table implementation */}
322
</div>
323
);
324
}
325
```
326
327
### State Update Utilities
328
329
Utilities for handling state updates and functional updates.
330
331
```javascript { .api }
332
/**
333
* Handles functional updates (updater functions or direct values)
334
* @param updater - Update function or direct value
335
* @param old - Previous value
336
* @returns New value
337
*/
338
function functionalUpdate<T>(
339
updater: T | ((old: T) => T),
340
old: T
341
): T;
342
```
343
344
**Usage Example:**
345
346
```javascript
347
import { functionalUpdate } from 'react-table';
348
349
// Custom state management with functional updates
350
function useCustomTableState(initialState) {
351
const [state, setState] = React.useState(initialState);
352
353
const updateState = React.useCallback((updater) => {
354
setState(prevState => functionalUpdate(updater, prevState));
355
}, []);
356
357
return [state, updateState];
358
}
359
360
// Usage
361
function MyTable() {
362
const [tableState, setTableState] = useCustomTableState({
363
filters: [],
364
sortBy: [],
365
});
366
367
// Direct value update
368
const clearFilters = () => {
369
setTableState({ ...tableState, filters: [] });
370
};
371
372
// Functional update
373
const addFilter = (filter) => {
374
setTableState(prevState => ({
375
...prevState,
376
filters: [...prevState.filters, filter],
377
}));
378
};
379
380
return (
381
<div>
382
{/* Table implementation */}
383
</div>
384
);
385
}
386
```
387
388
### Aggregation Functions
389
390
Built-in aggregation functions for grouped data.
391
392
```javascript { .api }
393
interface AggregationFunctions {
394
/** Sum of numeric values */
395
sum: (leafValues: any[]) => number;
396
/** Minimum value */
397
min: (leafValues: any[]) => any;
398
/** Maximum value */
399
max: (leafValues: any[]) => any;
400
/** Min-max range as string */
401
minMax: (leafValues: any[]) => string;
402
/** Average of values */
403
average: (leafValues: any[]) => number;
404
/** Median value */
405
median: (leafValues: any[]) => number;
406
/** Array of unique values */
407
unique: (leafValues: any[]) => any[];
408
/** Count of unique values */
409
uniqueCount: (leafValues: any[]) => number;
410
/** Total count */
411
count: (leafValues: any[]) => number;
412
}
413
```
414
415
**Usage Example:**
416
417
```javascript
418
import { useTable, useGroupBy } from 'react-table';
419
420
function GroupedTable({ columns, data }) {
421
const aggregationColumns = React.useMemo(() => [
422
...columns,
423
{
424
Header: 'Summary',
425
columns: [
426
{
427
Header: 'Total Sales',
428
accessor: 'sales',
429
aggregate: 'sum',
430
Aggregated: ({ value }) => `$${value.toLocaleString()}`,
431
},
432
{
433
Header: 'Avg Rating',
434
accessor: 'rating',
435
aggregate: 'average',
436
Aggregated: ({ value }) => Math.round(value * 100) / 100,
437
},
438
{
439
Header: 'Count',
440
accessor: 'id',
441
aggregate: 'count',
442
Aggregated: ({ value }) => `${value} items`,
443
},
444
],
445
},
446
], [columns]);
447
448
const tableInstance = useTable(
449
{
450
columns: aggregationColumns,
451
data,
452
},
453
useGroupBy
454
);
455
456
// Table implementation...
457
}
458
```
459
460
### Custom Utility Creation
461
462
Patterns for creating custom utilities that integrate with React Table.
463
464
```javascript
465
// Custom utility for table data export
466
function createExportUtility(tableInstance) {
467
const exportToCSV = () => {
468
const { flatHeaders, rows } = tableInstance;
469
470
// Create CSV header
471
const header = flatHeaders
472
.filter(header => header.isVisible)
473
.map(header => header.Header)
474
.join(',');
475
476
// Create CSV rows
477
const csvRows = rows.map(row => {
478
return flatHeaders
479
.filter(header => header.isVisible)
480
.map(header => {
481
const cell = row.cells.find(cell => cell.column.id === header.id);
482
return JSON.stringify(cell?.value || '');
483
})
484
.join(',');
485
});
486
487
// Combine and download
488
const csvContent = [header, ...csvRows].join('\n');
489
const blob = new Blob([csvContent], { type: 'text/csv' });
490
const url = URL.createObjectURL(blob);
491
492
const link = document.createElement('a');
493
link.href = url;
494
link.download = 'table-data.csv';
495
link.click();
496
497
URL.revokeObjectURL(url);
498
};
499
500
return { exportToCSV };
501
}
502
503
// Usage
504
function ExportableTable({ columns, data }) {
505
const tableInstance = useTable({ columns, data });
506
const { exportToCSV } = createExportUtility(tableInstance);
507
508
return (
509
<div>
510
<button onClick={exportToCSV}>
511
Export to CSV
512
</button>
513
{/* Table implementation */}
514
</div>
515
);
516
}
517
```
518
519
## Types
520
521
```javascript { .api }
522
interface ActionTypes {
523
init: string;
524
resetFilters: string;
525
setFilter: string;
526
setAllFilters: string;
527
resetSortBy: string;
528
setSortBy: string;
529
toggleSortBy: string;
530
resetGlobalFilter: string;
531
setGlobalFilter: string;
532
resetPage: string;
533
gotoPage: string;
534
setPageSize: string;
535
toggleAllRowsSelected: string;
536
toggleRowSelected: string;
537
toggleAllRowsExpanded: string;
538
toggleRowExpanded: string;
539
setColumnOrder: string;
540
resetSelectedRows: string;
541
resetExpanded: string;
542
resetGroupBy: string;
543
setGroupBy: string;
544
toggleGroupBy: string;
545
resetRowState: string;
546
setCellState: string;
547
resetPivot: string;
548
togglePivot: string;
549
}
550
551
interface UtilityMeta {
552
instance: TableInstance;
553
column?: Column;
554
row?: Row;
555
cell?: Cell;
556
}
557
```