0
# Components and Customization
1
2
Core building blocks and advanced customization options for creating custom grid rendering and specialized functionality.
3
4
## Capabilities
5
6
### Core Components
7
8
Low-level components that make up the grid structure, available for advanced customization scenarios.
9
10
```javascript { .api }
11
/** Core grid row component */
12
const Row: React.ComponentType<RowProps>;
13
14
/** Individual cell component */
15
const Cell: React.ComponentType<CellProps>;
16
17
/** Header cell component */
18
const HeaderCell: React.ComponentType<HeaderCellProps>;
19
20
/** Empty child row placeholder */
21
const EmptyChildRow: React.ComponentType<EmptyChildRowProps>;
22
```
23
24
### Row Component
25
26
Individual row component that renders a collection of cells.
27
28
```javascript { .api }
29
interface RowProps {
30
/** Row index in the dataset */
31
idx: number;
32
/** Starting column index for visible columns */
33
visibleStart: number;
34
/** Ending column index for visible columns */
35
visibleEnd: number;
36
/** Row data object */
37
row: any;
38
/** Row height in pixels */
39
height: number;
40
/** Array of column definitions */
41
columns: Column[];
42
/** Whether the row is selected */
43
isSelected?: boolean;
44
/** Whether the row is being scrolled */
45
isScrolling?: boolean;
46
/** CSS classes to apply to the row */
47
extraClasses?: string;
48
/** Function to get cell actions */
49
getCellActions?: (column: Column, row: any) => CellAction[];
50
/** Cell selection range */
51
cellSelection?: SelectionRange;
52
/** Event handlers for row interactions */
53
onRowClick?: (rowIdx: number, row: any) => void;
54
onRowDoubleClick?: (rowIdx: number, row: any) => void;
55
onCellClick?: (position: Position) => void;
56
onCellDoubleClick?: (position: Position) => void;
57
onCellContextMenu?: (position: Position) => void;
58
onDragEnter?: (overRowIdx: number) => void;
59
}
60
61
/**
62
* Row component for rendering individual grid rows
63
* Handles cell rendering, selection, and user interactions
64
*/
65
const Row: React.ComponentType<RowProps>;
66
```
67
68
### Cell Component
69
70
Individual cell component that handles content rendering, editing, and interactions.
71
72
```javascript { .api }
73
interface CellProps {
74
/** Column definition */
75
column: Column;
76
/** Cell value */
77
value: any;
78
/** Complete row data */
79
row: any;
80
/** Row index */
81
rowIdx: number;
82
/** Column index */
83
idx: number;
84
/** Whether the cell is selected */
85
isSelected?: boolean;
86
/** Whether the cell is being edited */
87
isEditing?: boolean;
88
/** Whether the cell can be copied */
89
isCopied?: boolean;
90
/** Cell height in pixels */
91
height: number;
92
/** Event handlers */
93
onCellClick?: (position: Position) => void;
94
onCellDoubleClick?: (position: Position) => void;
95
onCellContextMenu?: (position: Position) => void;
96
onCellExpand?: (args: CellExpandArgs) => void;
97
onCommit?: (args: CommitArgs) => void;
98
onCommitCancel?: () => void;
99
}
100
101
/**
102
* Cell component for rendering individual grid cells
103
* Handles content display, editing, and cell-specific interactions
104
*/
105
const Cell: React.ComponentType<CellProps>;
106
```
107
108
### HeaderCell Component
109
110
Header cell component for column headers with sorting, filtering, and resizing capabilities.
111
112
```javascript { .api }
113
interface HeaderCellProps {
114
/** Column definition */
115
column: Column;
116
/** Row type (header, filter, etc.) */
117
rowType: string;
118
/** Cell height in pixels */
119
height: number;
120
/** Event handlers */
121
onSort?: (columnKey: string, direction: SortDirection) => void;
122
onResize?: (column: Column, width: number) => void;
123
onHeaderDrop?: () => void;
124
onFilterChange?: (filter: Filter) => void;
125
/** Current sort configuration */
126
sortColumn?: string;
127
sortDirection?: SortDirection;
128
/** Whether the column can be dragged */
129
draggableHeaderCell?: React.ComponentType<any>;
130
}
131
132
/**
133
* Header cell component for column headers
134
* Supports sorting, filtering, resizing, and custom header rendering
135
*/
136
const HeaderCell: React.ComponentType<HeaderCellProps>;
137
```
138
139
### EmptyChildRow Component
140
141
Placeholder component for empty child rows in hierarchical data structures.
142
143
```javascript { .api }
144
interface EmptyChildRowProps {
145
/** Row height in pixels */
146
height: number;
147
/** Column definitions */
148
columns: Column[];
149
/** Additional CSS classes */
150
extraClasses?: string;
151
}
152
153
/**
154
* Empty child row component for hierarchical data
155
* Renders placeholder rows for expanded parent rows with no children
156
*/
157
const EmptyChildRow: React.ComponentType<EmptyChildRowProps>;
158
```
159
160
### Custom Component Integration
161
162
Using core components for advanced customization scenarios.
163
164
**Custom Row Renderer Example:**
165
166
```javascript
167
import React from 'react';
168
import ReactDataGrid, { Row } from 'react-data-grid';
169
170
const CustomRow = (props) => {
171
const { row, idx } = props;
172
173
// Add custom styling based on row data
174
const customStyle = {
175
backgroundColor: row.priority === 'high' ? '#fff3cd' : undefined,
176
fontWeight: row.isImportant ? 'bold' : 'normal'
177
};
178
179
return (
180
<div style={customStyle}>
181
<Row {...props} />
182
</div>
183
);
184
};
185
186
// Usage with custom row renderer
187
const GridWithCustomRows = () => {
188
return (
189
<ReactDataGrid
190
columns={columns}
191
rowGetter={i => rows[i]}
192
rowsCount={rows.length}
193
minHeight={400}
194
rowGroupRenderer={CustomRow}
195
/>
196
);
197
};
198
```
199
200
**Custom Cell Actions Example:**
201
202
```javascript
203
import ReactDataGrid from 'react-data-grid';
204
205
const getCellActions = (column, row) => {
206
if (column.key === 'actions') {
207
return [
208
{
209
icon: 'edit',
210
text: 'Edit',
211
callback: () => console.log('Edit:', row)
212
},
213
{
214
icon: 'delete',
215
text: 'Delete',
216
callback: () => console.log('Delete:', row)
217
}
218
];
219
}
220
return [];
221
};
222
223
const GridWithActions = () => {
224
return (
225
<ReactDataGrid
226
columns={columns}
227
rowGetter={i => rows[i]}
228
rowsCount={rows.length}
229
minHeight={400}
230
getCellActions={getCellActions}
231
/>
232
);
233
};
234
```
235
236
### Component Types and Interfaces
237
238
Supporting types and interfaces for component customization.
239
240
```javascript { .api }
241
interface Position {
242
/** Column index */
243
idx: number;
244
/** Row index */
245
rowIdx: number;
246
}
247
248
interface SelectionRange {
249
/** Top-left position */
250
topLeft: Position;
251
/** Bottom-right position */
252
bottomRight: Position;
253
}
254
255
interface CellAction {
256
/** Action icon identifier */
257
icon: string;
258
/** Display text for the action */
259
text: string;
260
/** Callback function when action is triggered */
261
callback: () => void;
262
/** Whether the action is disabled */
263
disabled?: boolean;
264
}
265
266
interface CellExpandArgs {
267
/** Row index */
268
rowIdx: number;
269
/** Column index */
270
idx: number;
271
/** Row data */
272
rowData: any;
273
/** Expand arguments */
274
expandArgs: any;
275
}
276
277
interface CommitArgs {
278
/** Cell position */
279
position: Position;
280
/** Updated value */
281
updated: any;
282
/** Update action type */
283
action: string;
284
}
285
```
286
287
### Advanced Customization
288
289
Complex customization scenarios using core components and custom renderers.
290
291
**Custom Header with Actions:**
292
293
```javascript
294
import React from 'react';
295
296
const CustomHeaderCell = ({ column, onSort, sortColumn, sortDirection }) => {
297
const handleSort = () => {
298
const newDirection =
299
sortColumn === column.key && sortDirection === 'ASC' ? 'DESC' : 'ASC';
300
onSort(column.key, newDirection);
301
};
302
303
const getSortIcon = () => {
304
if (sortColumn !== column.key) return 'βοΈ';
305
return sortDirection === 'ASC' ? 'β' : 'β';
306
};
307
308
return (
309
<div style={{
310
display: 'flex',
311
justifyContent: 'space-between',
312
alignItems: 'center',
313
padding: '8px'
314
}}>
315
<span>{column.name}</span>
316
<div style={{ display: 'flex', gap: '4px' }}>
317
{column.sortable && (
318
<button
319
onClick={handleSort}
320
style={{ border: 'none', background: 'none', cursor: 'pointer' }}
321
>
322
{getSortIcon()}
323
</button>
324
)}
325
<button
326
onClick={() => console.log('Filter', column.key)}
327
style={{ border: 'none', background: 'none', cursor: 'pointer' }}
328
>
329
π
330
</button>
331
</div>
332
</div>
333
);
334
};
335
336
// Usage in column definitions
337
const customColumns = [
338
{
339
key: 'id',
340
name: 'ID',
341
headerRenderer: <CustomHeaderCell />
342
},
343
{
344
key: 'name',
345
name: 'Name',
346
sortable: true,
347
headerRenderer: <CustomHeaderCell />
348
}
349
];
350
```
351
352
**Custom Cell with Rich Content:**
353
354
```javascript
355
const RichCell = ({ value, row, column }) => {
356
if (column.key === 'profile') {
357
return (
358
<div style={{
359
display: 'flex',
360
alignItems: 'center',
361
gap: '8px',
362
padding: '4px'
363
}}>
364
<img
365
src={row.avatar}
366
alt={row.name}
367
style={{
368
width: '32px',
369
height: '32px',
370
borderRadius: '50%'
371
}}
372
/>
373
<div>
374
<div style={{ fontWeight: 'bold' }}>{row.name}</div>
375
<div style={{ fontSize: '12px', color: '#666' }}>{row.email}</div>
376
</div>
377
</div>
378
);
379
}
380
381
return <div>{value}</div>;
382
};
383
384
const richColumns = [
385
{ key: 'id', name: 'ID' },
386
{
387
key: 'profile',
388
name: 'Profile',
389
formatter: <RichCell />
390
},
391
{ key: 'status', name: 'Status' }
392
];
393
```
394
395
**Custom Toolbar Integration:**
396
397
```javascript
398
const CustomToolbar = ({ onAddRow, onDeleteRows, selectedCount }) => {
399
return (
400
<div style={{
401
padding: '8px',
402
backgroundColor: '#f8f9fa',
403
borderBottom: '1px solid #dee2e6',
404
display: 'flex',
405
gap: '8px',
406
alignItems: 'center'
407
}}>
408
<button onClick={onAddRow}>Add Row</button>
409
<button
410
onClick={onDeleteRows}
411
disabled={selectedCount === 0}
412
>
413
Delete Selected ({selectedCount})
414
</button>
415
<div style={{ marginLeft: 'auto' }}>
416
Total: {rows.length} rows
417
</div>
418
</div>
419
);
420
};
421
422
const GridWithToolbar = () => {
423
const [selectedRows, setSelectedRows] = useState([]);
424
425
return (
426
<ReactDataGrid
427
columns={columns}
428
rowGetter={i => rows[i]}
429
rowsCount={rows.length}
430
minHeight={400}
431
toolbar={
432
<CustomToolbar
433
onAddRow={handleAddRow}
434
onDeleteRows={handleDeleteRows}
435
selectedCount={selectedRows.length}
436
/>
437
}
438
rowSelection={{
439
showCheckbox: true,
440
onRowsSelected: setSelectedRows,
441
selectBy: { indexes: selectedRows }
442
}}
443
/>
444
);
445
};
446
```
447
448
### Performance Optimization
449
450
Tips for optimizing custom components for better grid performance.
451
452
```javascript
453
import React, { memo, useMemo } from 'react';
454
455
// Memoized custom formatter
456
const OptimizedFormatter = memo(({ value, row, column }) => {
457
const processedValue = useMemo(() => {
458
return expensiveProcessing(value);
459
}, [value]);
460
461
return <div>{processedValue}</div>;
462
});
463
464
// Memoized row component
465
const OptimizedRow = memo((props) => {
466
return <Row {...props} />;
467
}, (prevProps, nextProps) => {
468
// Custom comparison logic
469
return (
470
prevProps.row === nextProps.row &&
471
prevProps.isSelected === nextProps.isSelected &&
472
prevProps.visibleStart === nextProps.visibleStart &&
473
prevProps.visibleEnd === nextProps.visibleEnd
474
);
475
});
476
```