0
# Column Management
1
2
React Table provides comprehensive column management capabilities including dynamic reordering, resizing, and visibility control. These features enable users to customize their table layout and optimize their data viewing experience.
3
4
## Capabilities
5
6
### Column Ordering (useColumnOrder)
7
8
Enables dynamic reordering of table columns through drag-and-drop or programmatic control.
9
10
```javascript { .api }
11
/**
12
* Adds column ordering capabilities to the table
13
* @param hooks - Hook registration object
14
*/
15
function useColumnOrder(hooks: Hooks): void;
16
17
interface ColumnOrderInstance {
18
/** Set the order of columns by column ID array */
19
setColumnOrder: (columnOrder: string[]) => void;
20
}
21
```
22
23
**Usage Example:**
24
25
```javascript
26
import React from 'react';
27
import { useTable, useColumnOrder } from 'react-table';
28
29
function ReorderableTable({ columns, data }) {
30
const {
31
getTableProps,
32
getTableBodyProps,
33
headerGroups,
34
rows,
35
prepareRow,
36
setColumnOrder,
37
allColumns,
38
} = useTable(
39
{
40
columns,
41
data,
42
},
43
useColumnOrder
44
);
45
46
// Example: Reverse column order
47
const reverseColumns = () => {
48
const currentOrder = allColumns.map(column => column.id);
49
setColumnOrder(currentOrder.reverse());
50
};
51
52
// Example: Reset to original order
53
const resetOrder = () => {
54
const originalOrder = columns.map((col, index) => col.id || col.accessor || index.toString());
55
setColumnOrder(originalOrder);
56
};
57
58
return (
59
<div>
60
<div>
61
<button onClick={reverseColumns}>
62
Reverse Column Order
63
</button>
64
<button onClick={resetOrder}>
65
Reset Order
66
</button>
67
</div>
68
69
<table {...getTableProps()}>
70
<thead>
71
{headerGroups.map(headerGroup => (
72
<tr {...headerGroup.getHeaderGroupProps()}>
73
{headerGroup.headers.map(column => (
74
<th
75
{...column.getHeaderProps()}
76
draggable
77
onDragStart={(e) => {
78
e.dataTransfer.setData('columnId', column.id);
79
}}
80
onDragOver={(e) => e.preventDefault()}
81
onDrop={(e) => {
82
e.preventDefault();
83
const draggedColumnId = e.dataTransfer.getData('columnId');
84
const targetColumnId = column.id;
85
86
if (draggedColumnId !== targetColumnId) {
87
const currentOrder = allColumns.map(col => col.id);
88
const draggedIndex = currentOrder.indexOf(draggedColumnId);
89
const targetIndex = currentOrder.indexOf(targetColumnId);
90
91
// Reorder array
92
const newOrder = [...currentOrder];
93
newOrder.splice(draggedIndex, 1);
94
newOrder.splice(targetIndex, 0, draggedColumnId);
95
96
setColumnOrder(newOrder);
97
}
98
}}
99
style={{ cursor: 'move' }}
100
>
101
{column.render('Header')}
102
</th>
103
))}
104
</tr>
105
))}
106
</thead>
107
<tbody {...getTableBodyProps()}>
108
{rows.map(row => {
109
prepareRow(row);
110
return (
111
<tr {...row.getRowProps()}>
112
{row.cells.map(cell => (
113
<td {...cell.getCellProps()}>
114
{cell.render('Cell')}
115
</td>
116
))}
117
</tr>
118
);
119
})}
120
</tbody>
121
</table>
122
</div>
123
);
124
}
125
```
126
127
### Column Resizing (useResizeColumns)
128
129
Enables interactive column width adjustment with drag handles and programmatic control.
130
131
```javascript { .api }
132
/**
133
* Adds column resizing capabilities to the table
134
* @param hooks - Hook registration object
135
*/
136
function useResizeColumns(hooks: Hooks): void;
137
138
interface ResizeColumnsInstance {
139
/** Total width of all columns */
140
totalColumnsWidth: number;
141
}
142
143
interface ResizeColumnInstance {
144
/** Whether this column can be resized */
145
canResize: boolean;
146
/** Whether this column is currently being resized */
147
isResizing: boolean;
148
/** Get props for the resize handle element */
149
getResizerProps: PropGetter;
150
}
151
```
152
153
**Usage Example:**
154
155
```javascript
156
import React from 'react';
157
import { useTable, useBlockLayout, useResizeColumns } from 'react-table';
158
159
function ResizableTable({ columns, data }) {
160
const defaultColumn = React.useMemo(
161
() => ({
162
minWidth: 30,
163
width: 150,
164
maxWidth: 400,
165
}),
166
[]
167
);
168
169
const {
170
getTableProps,
171
getTableBodyProps,
172
headerGroups,
173
rows,
174
prepareRow,
175
totalColumnsWidth,
176
} = useTable(
177
{
178
columns,
179
data,
180
defaultColumn,
181
},
182
useBlockLayout, // Required for resizing
183
useResizeColumns
184
);
185
186
return (
187
<div>
188
<div>Total Width: {totalColumnsWidth}px</div>
189
190
<div
191
{...getTableProps()}
192
style={{
193
display: 'inline-block',
194
border: '1px solid black',
195
}}
196
>
197
<div>
198
{headerGroups.map(headerGroup => (
199
<div {...headerGroup.getHeaderGroupProps()} className="tr">
200
{headerGroup.headers.map(column => (
201
<div {...column.getHeaderProps()} className="th">
202
{column.render('Header')}
203
{/* Resize handle */}
204
<div
205
{...column.getResizerProps()}
206
className={`resizer ${
207
column.isResizing ? 'isResizing' : ''
208
}`}
209
/>
210
</div>
211
))}
212
</div>
213
))}
214
</div>
215
216
<div {...getTableBodyProps()}>
217
{rows.map(row => {
218
prepareRow(row);
219
return (
220
<div {...row.getRowProps()} className="tr">
221
{row.cells.map(cell => (
222
<div {...cell.getCellProps()} className="td">
223
{cell.render('Cell')}
224
</div>
225
))}
226
</div>
227
);
228
})}
229
</div>
230
</div>
231
232
<style jsx>{`
233
.th,
234
.td {
235
margin: 0;
236
padding: 0.5rem;
237
border-bottom: 1px solid black;
238
border-right: 1px solid black;
239
position: relative;
240
display: inline-block;
241
box-sizing: border-box;
242
overflow: hidden;
243
}
244
245
.th {
246
font-weight: bold;
247
}
248
249
.resizer {
250
display: inline-block;
251
background: blue;
252
width: 5px;
253
height: 100%;
254
position: absolute;
255
right: 0;
256
top: 0;
257
transform: translateX(50%);
258
z-index: 1;
259
cursor: col-resize;
260
}
261
262
.resizer.isResizing {
263
background: red;
264
}
265
`}</style>
266
</div>
267
);
268
}
269
```
270
271
### Column Visibility (useColumnVisibility)
272
273
Built-in column visibility management (automatically included with useTable).
274
275
```javascript { .api }
276
interface ColumnVisibilityInstance {
277
/** All columns including hidden ones */
278
allColumns: Column[];
279
/** Currently visible columns */
280
visibleColumns: Column[];
281
/** Toggle visibility for all columns */
282
toggleAllColumnsVisible: (visible?: boolean) => void;
283
/** Get props for toggle all columns visibility */
284
getToggleAllColumnsVisibleProps: PropGetter;
285
}
286
287
interface ColumnVisibilityColumnInstance {
288
/** Whether this column is visible */
289
isVisible: boolean;
290
/** Toggle visibility for this column */
291
toggleColumnVisible: (visible?: boolean) => void;
292
/** Get props for column visibility toggle */
293
getToggleColumnVisibleProps: PropGetter;
294
}
295
```
296
297
**Usage Example:**
298
299
```javascript
300
import React from 'react';
301
import { useTable } from 'react-table';
302
303
function TableWithColumnToggle({ columns, data }) {
304
const {
305
getTableProps,
306
getTableBodyProps,
307
headerGroups,
308
rows,
309
prepareRow,
310
allColumns,
311
getToggleAllColumnsVisibleProps,
312
} = useTable({
313
columns,
314
data,
315
});
316
317
return (
318
<div>
319
{/* Column Visibility Controls */}
320
<div>
321
<div>
322
<label>
323
<input
324
type="checkbox"
325
{...getToggleAllColumnsVisibleProps()}
326
/>{' '}
327
Toggle All
328
</label>
329
</div>
330
{allColumns.map(column => (
331
<div key={column.id}>
332
<label>
333
<input
334
type="checkbox"
335
{...column.getToggleColumnVisibleProps()}
336
/>{' '}
337
{column.Header}
338
</label>
339
</div>
340
))}
341
</div>
342
343
<table {...getTableProps()}>
344
<thead>
345
{headerGroups.map(headerGroup => (
346
<tr {...headerGroup.getHeaderGroupProps()}>
347
{headerGroup.headers.map(column => (
348
<th {...column.getHeaderProps()}>
349
{column.render('Header')}
350
</th>
351
))}
352
</tr>
353
))}
354
</thead>
355
<tbody {...getTableBodyProps()}>
356
{rows.map(row => {
357
prepareRow(row);
358
return (
359
<tr {...row.getRowProps()}>
360
{row.cells.map(cell => (
361
<td {...cell.getCellProps()}>
362
{cell.render('Cell')}
363
</td>
364
))}
365
</tr>
366
);
367
})}
368
</tbody>
369
</table>
370
</div>
371
);
372
}
373
```
374
375
### Combined Column Management
376
377
Combine multiple column management features for maximum flexibility.
378
379
```javascript
380
import React from 'react';
381
import {
382
useTable,
383
useColumnOrder,
384
useBlockLayout,
385
useResizeColumns
386
} from 'react-table';
387
388
function AdvancedColumnTable({ columns, data }) {
389
const [columnVisibility, setColumnVisibility] = React.useState({});
390
391
const defaultColumn = React.useMemo(
392
() => ({
393
minWidth: 50,
394
width: 200,
395
maxWidth: 500,
396
}),
397
[]
398
);
399
400
const {
401
getTableProps,
402
getTableBodyProps,
403
headerGroups,
404
rows,
405
prepareRow,
406
allColumns,
407
setColumnOrder,
408
totalColumnsWidth,
409
} = useTable(
410
{
411
columns,
412
data,
413
defaultColumn,
414
initialState: {
415
hiddenColumns: Object.keys(columnVisibility).filter(
416
key => !columnVisibility[key]
417
),
418
},
419
},
420
useColumnOrder,
421
useBlockLayout,
422
useResizeColumns
423
);
424
425
return (
426
<div>
427
{/* Column Management Controls */}
428
<div style={{ marginBottom: '20px' }}>
429
<h3>Column Management</h3>
430
431
{/* Visibility Controls */}
432
<div>
433
<h4>Visibility</h4>
434
{allColumns.map(column => (
435
<label key={column.id} style={{ marginRight: '10px' }}>
436
<input
437
type="checkbox"
438
{...column.getToggleColumnVisibleProps()}
439
/>
440
{column.Header}
441
</label>
442
))}
443
</div>
444
445
{/* Order Controls */}
446
<div>
447
<h4>Order</h4>
448
<button
449
onClick={() => {
450
const currentOrder = allColumns.map(col => col.id);
451
setColumnOrder(currentOrder.reverse());
452
}}
453
>
454
Reverse Order
455
</button>
456
</div>
457
</div>
458
459
{/* Resizable Table */}
460
<div style={{ overflow: 'auto' }}>
461
<div {...getTableProps()} className="table">
462
<div>
463
{headerGroups.map(headerGroup => (
464
<div {...headerGroup.getHeaderGroupProps()} className="tr">
465
{headerGroup.headers.map(column => (
466
<div {...column.getHeaderProps()} className="th">
467
<div className="header-content">
468
{column.render('Header')}
469
{column.canResize && (
470
<div
471
{...column.getResizerProps()}
472
className={`resizer ${
473
column.isResizing ? 'isResizing' : ''
474
}`}
475
/>
476
)}
477
</div>
478
</div>
479
))}
480
</div>
481
))}
482
</div>
483
484
<div {...getTableBodyProps()}>
485
{rows.map(row => {
486
prepareRow(row);
487
return (
488
<div {...row.getRowProps()} className="tr">
489
{row.cells.map(cell => (
490
<div {...cell.getCellProps()} className="td">
491
{cell.render('Cell')}
492
</div>
493
))}
494
</div>
495
);
496
})}
497
</div>
498
</div>
499
</div>
500
501
<div>
502
Total table width: {totalColumnsWidth}px
503
</div>
504
</div>
505
);
506
}
507
```
508
509
## Types
510
511
```javascript { .api }
512
interface TableState {
513
/** Column order by column IDs */
514
columnOrder: string[];
515
/** Hidden column IDs */
516
hiddenColumns: string[];
517
/** Column resizing state */
518
columnResizing: {
519
columnSizes: Record<string, number>;
520
headerIdWidths: Record<string, number>;
521
columnWidth: number;
522
isResizingColumn?: string;
523
};
524
}
525
526
interface ColumnManagementMeta {
527
instance: TableInstance;
528
column: Column;
529
}
530
```