0
# Layout Systems
1
2
React Table provides specialized layout plugins that enable different rendering approaches for tables. These layout systems optimize performance and provide specific styling capabilities for different use cases.
3
4
## Capabilities
5
6
### Absolute Layout (useAbsoluteLayout)
7
8
Provides absolute positioning layout for high-performance tables with fixed dimensions.
9
10
```javascript { .api }
11
/**
12
* Adds absolute positioning layout to the table
13
* @param hooks - Hook registration object
14
*/
15
function useAbsoluteLayout(hooks: Hooks): void;
16
```
17
18
**Usage Example:**
19
20
```javascript
21
import React from 'react';
22
import { useTable, useAbsoluteLayout } from 'react-table';
23
24
function AbsoluteLayoutTable({ columns, data }) {
25
const defaultColumn = React.useMemo(
26
() => ({
27
width: 150,
28
}),
29
[]
30
);
31
32
const {
33
getTableProps,
34
getTableBodyProps,
35
headerGroups,
36
rows,
37
prepareRow,
38
totalColumnsWidth,
39
} = useTable(
40
{
41
columns,
42
data,
43
defaultColumn,
44
},
45
useAbsoluteLayout
46
);
47
48
return (
49
<div
50
{...getTableProps()}
51
style={{
52
position: 'relative',
53
width: totalColumnsWidth,
54
height: 400,
55
overflow: 'auto',
56
border: '1px solid black',
57
}}
58
>
59
<div>
60
{headerGroups.map(headerGroup => (
61
<div {...headerGroup.getHeaderGroupProps()} className="tr">
62
{headerGroup.headers.map(column => (
63
<div {...column.getHeaderProps()} className="th">
64
{column.render('Header')}
65
</div>
66
))}
67
</div>
68
))}
69
</div>
70
71
<div {...getTableBodyProps()}>
72
{rows.map(row => {
73
prepareRow(row);
74
return (
75
<div {...row.getRowProps()} className="tr">
76
{row.cells.map(cell => (
77
<div {...cell.getCellProps()} className="td">
78
{cell.render('Cell')}
79
</div>
80
))}
81
</div>
82
);
83
})}
84
</div>
85
</div>
86
);
87
}
88
```
89
90
### Block Layout (useBlockLayout)
91
92
Provides block-level layout with explicit width management for consistent column sizing.
93
94
```javascript { .api }
95
/**
96
* Adds block layout to the table
97
* @param hooks - Hook registration object
98
*/
99
function useBlockLayout(hooks: Hooks): void;
100
```
101
102
**Usage Example:**
103
104
```javascript
105
import React from 'react';
106
import { useTable, useBlockLayout, useResizeColumns } from 'react-table';
107
108
function BlockLayoutTable({ columns, data }) {
109
const defaultColumn = React.useMemo(
110
() => ({
111
minWidth: 30,
112
width: 150,
113
maxWidth: 400,
114
}),
115
[]
116
);
117
118
const {
119
getTableProps,
120
getTableBodyProps,
121
headerGroups,
122
rows,
123
prepareRow,
124
} = useTable(
125
{
126
columns,
127
data,
128
defaultColumn,
129
},
130
useBlockLayout,
131
useResizeColumns
132
);
133
134
return (
135
<div
136
{...getTableProps()}
137
style={{
138
display: 'inline-block',
139
border: '1px solid black',
140
}}
141
>
142
<div>
143
{headerGroups.map(headerGroup => (
144
<div {...headerGroup.getHeaderGroupProps()} className="header-group">
145
{headerGroup.headers.map(column => (
146
<div {...column.getHeaderProps()} className="header">
147
{column.render('Header')}
148
{column.canResize && (
149
<div
150
{...column.getResizerProps()}
151
className="resizer"
152
/>
153
)}
154
</div>
155
))}
156
</div>
157
))}
158
</div>
159
160
<div {...getTableBodyProps()}>
161
{rows.map(row => {
162
prepareRow(row);
163
return (
164
<div {...row.getRowProps()} className="row">
165
{row.cells.map(cell => (
166
<div {...cell.getCellProps()} className="cell">
167
{cell.render('Cell')}
168
</div>
169
))}
170
</div>
171
);
172
})}
173
</div>
174
175
<style jsx>{`
176
.header-group {
177
display: flex;
178
}
179
.header {
180
position: relative;
181
background: #f5f5f5;
182
border: 1px solid #ddd;
183
padding: 8px;
184
font-weight: bold;
185
}
186
.row {
187
display: flex;
188
}
189
.cell {
190
border: 1px solid #ddd;
191
padding: 8px;
192
overflow: hidden;
193
}
194
.resizer {
195
position: absolute;
196
right: 0;
197
top: 0;
198
height: 100%;
199
width: 5px;
200
background: rgba(0, 0, 0, 0.5);
201
cursor: col-resize;
202
user-select: none;
203
touch-action: none;
204
}
205
`}</style>
206
</div>
207
);
208
}
209
```
210
211
### Flex Layout (useFlexLayout)
212
213
Provides flexbox-based layout for responsive and flexible column sizing.
214
215
```javascript { .api }
216
/**
217
* Adds flexbox layout to the table
218
* @param hooks - Hook registration object
219
*/
220
function useFlexLayout(hooks: Hooks): void;
221
```
222
223
**Usage Example:**
224
225
```javascript
226
import React from 'react';
227
import { useTable, useFlexLayout } from 'react-table';
228
229
function FlexLayoutTable({ columns, data }) {
230
const {
231
getTableProps,
232
getTableBodyProps,
233
headerGroups,
234
rows,
235
prepareRow,
236
} = useTable(
237
{
238
columns,
239
data,
240
},
241
useFlexLayout
242
);
243
244
return (
245
<div
246
{...getTableProps()}
247
style={{
248
display: 'flex',
249
flexDirection: 'column',
250
border: '1px solid black',
251
maxWidth: '100%',
252
}}
253
>
254
<div>
255
{headerGroups.map(headerGroup => (
256
<div
257
{...headerGroup.getHeaderGroupProps()}
258
style={{
259
display: 'flex',
260
backgroundColor: '#f5f5f5',
261
}}
262
>
263
{headerGroup.headers.map(column => (
264
<div
265
{...column.getHeaderProps()}
266
style={{
267
padding: '10px',
268
border: '1px solid #ddd',
269
fontWeight: 'bold',
270
flex: column.totalFlexWidth ? `${column.totalFlexWidth} 0 auto` : '1 1 auto',
271
}}
272
>
273
{column.render('Header')}
274
</div>
275
))}
276
</div>
277
))}
278
</div>
279
280
<div {...getTableBodyProps()}>
281
{rows.map(row => {
282
prepareRow(row);
283
return (
284
<div
285
{...row.getRowProps()}
286
style={{
287
display: 'flex',
288
}}
289
>
290
{row.cells.map(cell => (
291
<div
292
{...cell.getCellProps()}
293
style={{
294
padding: '10px',
295
border: '1px solid #ddd',
296
flex: cell.column.totalFlexWidth ? `${cell.column.totalFlexWidth} 0 auto` : '1 1 auto',
297
overflow: 'hidden',
298
}}
299
>
300
{cell.render('Cell')}
301
</div>
302
))}
303
</div>
304
);
305
})}
306
</div>
307
</div>
308
);
309
}
310
```
311
312
### Grid Layout (useGridLayout)
313
314
Provides CSS Grid-based layout for advanced grid positioning and alignment.
315
316
```javascript { .api }
317
/**
318
* Adds CSS Grid layout to the table
319
* @param hooks - Hook registration object
320
*/
321
function useGridLayout(hooks: Hooks): void;
322
```
323
324
**Usage Example:**
325
326
```javascript
327
import React from 'react';
328
import { useTable, useGridLayout } from 'react-table';
329
330
function GridLayoutTable({ columns, data }) {
331
const {
332
getTableProps,
333
getTableBodyProps,
334
headerGroups,
335
rows,
336
prepareRow,
337
} = useTable(
338
{
339
columns,
340
data,
341
},
342
useGridLayout
343
);
344
345
// Calculate grid template columns
346
const gridTemplateColumns = headerGroups[0]?.headers
347
.map(column => column.width || '1fr')
348
.join(' ') || 'repeat(auto-fit, minmax(150px, 1fr))';
349
350
return (
351
<div
352
{...getTableProps()}
353
style={{
354
display: 'grid',
355
gridTemplateColumns,
356
border: '1px solid black',
357
gap: '1px',
358
backgroundColor: '#ddd',
359
}}
360
>
361
{/* Headers */}
362
{headerGroups.map(headerGroup =>
363
headerGroup.headers.map(column => (
364
<div
365
key={column.id}
366
{...column.getHeaderProps()}
367
style={{
368
padding: '10px',
369
backgroundColor: '#f5f5f5',
370
fontWeight: 'bold',
371
display: 'flex',
372
alignItems: 'center',
373
}}
374
>
375
{column.render('Header')}
376
</div>
377
))
378
)}
379
380
{/* Body Cells */}
381
{rows.map(row => {
382
prepareRow(row);
383
return row.cells.map(cell => (
384
<div
385
key={`${row.id}-${cell.column.id}`}
386
{...cell.getCellProps()}
387
style={{
388
padding: '10px',
389
backgroundColor: 'white',
390
display: 'flex',
391
alignItems: 'center',
392
}}
393
>
394
{cell.render('Cell')}
395
</div>
396
));
397
})}
398
</div>
399
);
400
}
401
```
402
403
### Layout Comparison and Use Cases
404
405
**When to use each layout:**
406
407
| Layout | Use Case | Pros | Cons |
408
|--------|----------|------|------|
409
| **Default** | Simple tables, basic styling | Easy to style with CSS, familiar table markup | Less control over column sizing |
410
| **Absolute** | High-performance, virtualization | Best performance, precise positioning | Requires fixed dimensions |
411
| **Block** | Resizable columns, precise widths | Works well with resizing, precise control | More complex CSS |
412
| **Flex** | Responsive tables, flexible sizing | Responsive, flexible column distribution | Can be complex with many columns |
413
| **Grid** | Complex layouts, advanced alignment | Powerful grid features, clean markup | Browser support considerations |
414
415
### Layout with Virtualization
416
417
Combine layout plugins with virtualization for handling large datasets.
418
419
```javascript
420
import React from 'react';
421
import { FixedSizeList as List } from 'react-window';
422
import { useTable, useBlockLayout } from 'react-table';
423
424
function VirtualizedTable({ columns, data }) {
425
const defaultColumn = React.useMemo(
426
() => ({
427
width: 150,
428
}),
429
[]
430
);
431
432
const {
433
getTableProps,
434
getTableBodyProps,
435
headerGroups,
436
rows,
437
totalColumnsWidth,
438
prepareRow,
439
} = useTable(
440
{
441
columns,
442
data,
443
defaultColumn,
444
},
445
useBlockLayout
446
);
447
448
const RenderRow = React.useCallback(
449
({ index, style }) => {
450
const row = rows[index];
451
prepareRow(row);
452
return (
453
<div
454
{...row.getRowProps({ style })}
455
className="row"
456
>
457
{row.cells.map(cell => (
458
<div {...cell.getCellProps()} className="cell">
459
{cell.render('Cell')}
460
</div>
461
))}
462
</div>
463
);
464
},
465
[prepareRow, rows]
466
);
467
468
return (
469
<div {...getTableProps()}>
470
<div>
471
{headerGroups.map(headerGroup => (
472
<div {...headerGroup.getHeaderGroupProps()} className="header-group">
473
{headerGroup.headers.map(column => (
474
<div {...column.getHeaderProps()} className="header">
475
{column.render('Header')}
476
</div>
477
))}
478
</div>
479
))}
480
</div>
481
482
<div {...getTableBodyProps()}>
483
<List
484
height={400}
485
itemCount={rows.length}
486
itemSize={35}
487
width={totalColumnsWidth}
488
>
489
{RenderRow}
490
</List>
491
</div>
492
</div>
493
);
494
}
495
```
496
497
### Custom Layout Implementation
498
499
Create custom layout behaviors by implementing your own layout hook.
500
501
```javascript
502
// Custom layout hook example
503
function useCustomLayout(hooks) {
504
hooks.getTableProps.push((props, { instance }) => [
505
props,
506
{
507
style: {
508
display: 'table',
509
borderCollapse: 'collapse',
510
width: '100%',
511
},
512
},
513
]);
514
515
hooks.getHeaderGroupProps.push((props) => [
516
props,
517
{
518
style: {
519
display: 'table-row',
520
},
521
},
522
]);
523
524
hooks.getHeaderProps.push((props, { column }) => [
525
props,
526
{
527
style: {
528
display: 'table-cell',
529
padding: '8px',
530
border: '1px solid #ccc',
531
backgroundColor: '#f5f5f5',
532
fontWeight: 'bold',
533
width: column.width,
534
},
535
},
536
]);
537
538
hooks.getRowProps.push((props) => [
539
props,
540
{
541
style: {
542
display: 'table-row',
543
},
544
},
545
]);
546
547
hooks.getCellProps.push((props, { cell }) => [
548
props,
549
{
550
style: {
551
display: 'table-cell',
552
padding: '8px',
553
border: '1px solid #ccc',
554
width: cell.column.width,
555
},
556
},
557
]);
558
}
559
560
// Use custom layout
561
function CustomLayoutTable({ columns, data }) {
562
const tableInstance = useTable(
563
{ columns, data },
564
useCustomLayout
565
);
566
567
// Table implementation...
568
}
569
```
570
571
## Types
572
573
```javascript { .api }
574
interface LayoutInstance {
575
/** Total width of all columns */
576
totalColumnsWidth?: number;
577
}
578
579
interface LayoutColumn {
580
/** Column width */
581
width?: number;
582
/** Minimum column width */
583
minWidth?: number;
584
/** Maximum column width */
585
maxWidth?: number;
586
/** Flex width for flex layout */
587
totalFlexWidth?: number;
588
}
589
590
interface LayoutMeta {
591
instance: TableInstance;
592
column?: Column;
593
row?: Row;
594
cell?: Cell;
595
}
596
```