0
# Data Management
1
2
RC Tree supports flexible data management through both JSX children and data-driven approaches, with customizable field mappings and comprehensive type-safe data structures.
3
4
## Capabilities
5
6
### Data Structure Types
7
8
Core data types for representing tree nodes with comprehensive type safety and customization options.
9
10
```typescript { .api }
11
/**
12
* Base interface for tree data nodes with common properties
13
*/
14
interface BasicDataNode {
15
/** Enable/disable checkbox for this node */
16
checkable?: boolean;
17
/** Disable all interactions for this node */
18
disabled?: boolean;
19
/** Disable only checkbox interactions */
20
disableCheckbox?: boolean;
21
/** Custom icon for this node */
22
icon?: IconType;
23
/** Mark as leaf node (no children) */
24
isLeaf?: boolean;
25
/** Enable/disable selection for this node */
26
selectable?: boolean;
27
/** Custom expand/collapse icon */
28
switcherIcon?: IconType;
29
/** CSS class for styling */
30
className?: string;
31
/** Inline styles */
32
style?: React.CSSProperties;
33
}
34
35
/**
36
* Generic wrapper type for custom data with tree functionality
37
* @param T - Custom data type
38
* @param ChildFieldName - Field name for children array (default: 'children')
39
*/
40
type FieldDataNode<T, ChildFieldName extends string = 'children'> = BasicDataNode &
41
T &
42
Partial<Record<ChildFieldName, FieldDataNode<T, ChildFieldName>[]>>;
43
44
/**
45
* Standard data node structure with key and title
46
*/
47
type DataNode = FieldDataNode<{
48
key: Key;
49
title?: React.ReactNode | ((data: DataNode) => React.ReactNode);
50
}>;
51
52
/**
53
* Enhanced data node with event state information
54
*/
55
type EventDataNode<TreeDataType> = {
56
key: Key;
57
expanded: boolean;
58
selected: boolean;
59
checked: boolean;
60
loaded: boolean;
61
loading: boolean;
62
halfChecked: boolean;
63
dragOver: boolean;
64
dragOverGapTop: boolean;
65
dragOverGapBottom: boolean;
66
pos: string;
67
active: boolean;
68
} & TreeDataType & BasicDataNode;
69
```
70
71
### Field Name Mapping
72
73
Customize field names for data-driven trees to work with existing data structures.
74
75
```typescript { .api }
76
/**
77
* Configuration for mapping custom field names to tree properties
78
*/
79
interface FieldNames {
80
/** Field name for node display title (default: 'title') */
81
title?: string;
82
/** Internal title field mapping for complex scenarios */
83
_title?: string[];
84
/** Field name for unique node identifier (default: 'key') */
85
key?: string;
86
/** Field name for child nodes array (default: 'children') */
87
children?: string;
88
}
89
```
90
91
**Usage Examples:**
92
93
### Basic Data-Driven Tree
94
95
```typescript
96
import React, { useState } from "react";
97
import Tree from "rc-tree";
98
99
const BasicDataTree = () => {
100
const treeData = [
101
{
102
key: '0-0',
103
title: 'Parent Node',
104
children: [
105
{
106
key: '0-0-0',
107
title: 'Child Node 1',
108
isLeaf: true,
109
},
110
{
111
key: '0-0-1',
112
title: 'Child Node 2',
113
children: [
114
{
115
key: '0-0-1-0',
116
title: 'Grandchild Node',
117
isLeaf: true,
118
},
119
],
120
},
121
],
122
},
123
];
124
125
return (
126
<Tree
127
prefixCls="rc-tree"
128
treeData={treeData}
129
defaultExpandAll
130
/>
131
);
132
};
133
```
134
135
### Custom Field Mapping
136
137
```typescript
138
import React from "react";
139
import Tree from "rc-tree";
140
141
const CustomFieldTree = () => {
142
// Data with custom field names
143
const customData = [
144
{
145
id: '1',
146
name: 'Root Category',
147
subcategories: [
148
{
149
id: '1-1',
150
name: 'Electronics',
151
subcategories: [
152
{ id: '1-1-1', name: 'Phones' },
153
{ id: '1-1-2', name: 'Laptops' },
154
],
155
},
156
{
157
id: '1-2',
158
name: 'Books',
159
subcategories: [],
160
},
161
],
162
},
163
];
164
165
const fieldNames = {
166
title: 'name',
167
key: 'id',
168
children: 'subcategories',
169
};
170
171
return (
172
<Tree
173
prefixCls="rc-tree"
174
treeData={customData}
175
fieldNames={fieldNames}
176
defaultExpandAll
177
/>
178
);
179
};
180
```
181
182
### Rich Data with Custom Properties
183
184
```typescript
185
import React from "react";
186
import Tree from "rc-tree";
187
188
interface CustomNodeData {
189
key: string;
190
title: string;
191
type: 'folder' | 'file';
192
size?: number;
193
modified?: Date;
194
children?: CustomNodeData[];
195
}
196
197
const RichDataTree = () => {
198
const richTreeData: CustomNodeData[] = [
199
{
200
key: '0-0',
201
title: 'Documents',
202
type: 'folder',
203
modified: new Date('2024-01-15'),
204
children: [
205
{
206
key: '0-0-0',
207
title: 'report.pdf',
208
type: 'file',
209
size: 2048,
210
modified: new Date('2024-01-10'),
211
isLeaf: true,
212
},
213
{
214
key: '0-0-1',
215
title: 'presentation.pptx',
216
type: 'file',
217
size: 5120,
218
modified: new Date('2024-01-12'),
219
isLeaf: true,
220
disabled: true, // File is read-only
221
},
222
],
223
},
224
];
225
226
const titleRender = (nodeData: CustomNodeData) => (
227
<span>
228
{nodeData.type === 'folder' ? 'π' : 'π'} {nodeData.title}
229
{nodeData.size && (
230
<span style={{ color: '#999', marginLeft: 8 }}>
231
({Math.round(nodeData.size / 1024)}KB)
232
</span>
233
)}
234
</span>
235
);
236
237
return (
238
<Tree
239
prefixCls="rc-tree"
240
treeData={richTreeData}
241
titleRender={titleRender}
242
defaultExpandAll
243
/>
244
);
245
};
246
```
247
248
### Dynamic Data with Async Loading
249
250
```typescript
251
import React, { useState } from "react";
252
import Tree from "rc-tree";
253
254
interface AsyncNodeData {
255
key: string;
256
title: string;
257
isLeaf?: boolean;
258
children?: AsyncNodeData[];
259
}
260
261
const AsyncDataTree = () => {
262
const [treeData, setTreeData] = useState<AsyncNodeData[]>([
263
{
264
key: '0-0',
265
title: 'Lazy Parent',
266
children: [], // Empty children for lazy loading
267
},
268
]);
269
const [loadedKeys, setLoadedKeys] = useState<string[]>([]);
270
271
const loadData = async (treeNode: any) => {
272
const { key } = treeNode;
273
274
// Simulate API call
275
await new Promise(resolve => setTimeout(resolve, 1000));
276
277
// Generate children data
278
const children = [
279
{
280
key: `${key}-0`,
281
title: `Child ${key}-0`,
282
isLeaf: true,
283
},
284
{
285
key: `${key}-1`,
286
title: `Child ${key}-1`,
287
isLeaf: true,
288
},
289
];
290
291
// Update tree data
292
setTreeData(prevData => {
293
const updateNode = (nodes: AsyncNodeData[]): AsyncNodeData[] => {
294
return nodes.map(node => {
295
if (node.key === key) {
296
return { ...node, children };
297
}
298
if (node.children) {
299
return { ...node, children: updateNode(node.children) };
300
}
301
return node;
302
});
303
};
304
return updateNode(prevData);
305
});
306
307
setLoadedKeys(prev => [...prev, key]);
308
};
309
310
return (
311
<Tree
312
prefixCls="rc-tree"
313
treeData={treeData}
314
loadData={loadData}
315
loadedKeys={loadedKeys}
316
/>
317
);
318
};
319
```
320
321
## Data Structure Patterns
322
323
### Flat Data Conversion
324
325
```typescript { .api }
326
/**
327
* Convert flat array data to hierarchical tree structure
328
*/
329
interface FlatDataItem {
330
id: string;
331
parentId?: string;
332
title: string;
333
[key: string]: any;
334
}
335
336
/**
337
* Utility type for flattened tree node with hierarchy information
338
*/
339
interface FlattenNode<TreeDataType extends BasicDataNode = DataNode> {
340
parent: FlattenNode<TreeDataType> | null;
341
children: FlattenNode<TreeDataType>[];
342
pos: string;
343
data: TreeDataType;
344
title: React.ReactNode;
345
key: Key;
346
isStart: boolean[];
347
isEnd: boolean[];
348
}
349
```
350
351
**Usage Example:**
352
353
```typescript
354
import React from "react";
355
import Tree from "rc-tree";
356
357
const FlatDataTree = () => {
358
const flatData = [
359
{ id: '1', title: 'Root' },
360
{ id: '2', parentId: '1', title: 'Child 1' },
361
{ id: '3', parentId: '1', title: 'Child 2' },
362
{ id: '4', parentId: '2', title: 'Grandchild 1' },
363
];
364
365
// Convert flat data to tree structure
366
const buildTreeData = (flatData: any[]) => {
367
const map = new Map();
368
const roots: any[] = [];
369
370
// Create map of all items
371
flatData.forEach(item => {
372
map.set(item.id, { ...item, key: item.id, children: [] });
373
});
374
375
// Build tree structure
376
flatData.forEach(item => {
377
const node = map.get(item.id);
378
if (item.parentId) {
379
const parent = map.get(item.parentId);
380
if (parent) {
381
parent.children.push(node);
382
}
383
} else {
384
roots.push(node);
385
}
386
});
387
388
return roots;
389
};
390
391
const treeData = buildTreeData(flatData);
392
393
return (
394
<Tree
395
prefixCls="rc-tree"
396
treeData={treeData}
397
defaultExpandAll
398
/>
399
);
400
};
401
```
402
403
### Type-Safe Custom Data
404
405
```typescript
406
import React from "react";
407
import Tree from "rc-tree";
408
409
// Define your custom data structure
410
interface FileSystemNode {
411
key: string;
412
title: string;
413
type: 'file' | 'directory';
414
permissions: string;
415
owner: string;
416
size?: number;
417
children?: FileSystemNode[];
418
}
419
420
const TypeSafeDataTree = () => {
421
const fileSystemData: FileSystemNode[] = [
422
{
423
key: '/home',
424
title: 'home',
425
type: 'directory',
426
permissions: 'drwxr-xr-x',
427
owner: 'root',
428
children: [
429
{
430
key: '/home/user',
431
title: 'user',
432
type: 'directory',
433
permissions: 'drwxr-xr-x',
434
owner: 'user',
435
children: [
436
{
437
key: '/home/user/document.txt',
438
title: 'document.txt',
439
type: 'file',
440
permissions: '-rw-r--r--',
441
owner: 'user',
442
size: 1024,
443
isLeaf: true,
444
},
445
],
446
},
447
],
448
},
449
];
450
451
return (
452
<Tree<FileSystemNode>
453
prefixCls="rc-tree"
454
treeData={fileSystemData}
455
titleRender={(node) => (
456
<span>
457
{node.type === 'directory' ? 'π' : 'π'} {node.title}
458
<span style={{ color: '#666', fontSize: '0.8em', marginLeft: 8 }}>
459
{node.permissions} {node.owner}
460
</span>
461
</span>
462
)}
463
defaultExpandAll
464
/>
465
);
466
};
467
```
468
469
## Key Management
470
471
### Key Requirements
472
473
```typescript { .api }
474
/**
475
* Key types for tree node identification
476
*/
477
type Key = React.Key; // string | number
478
type SafeKey = Exclude<Key, bigint>; // Excludes bigint for index compatibility
479
480
/**
481
* Key entity mapping for efficient tree operations
482
*/
483
type KeyEntities<DateType extends BasicDataNode = any> = Record<
484
SafeKey,
485
DataEntity<DateType>
486
>;
487
488
/**
489
* Data entity with hierarchy information
490
*/
491
interface DataEntity<TreeDataType extends BasicDataNode = DataNode> {
492
node: TreeDataType;
493
nodes: TreeDataType[];
494
key: Key;
495
pos: string;
496
index: number;
497
parent?: DataEntity<TreeDataType>;
498
children?: DataEntity<TreeDataType>[];
499
level: number;
500
}
501
```
502
503
**Key Management Best Practices:**
504
505
```typescript
506
// β Good: Unique, stable keys
507
const goodTreeData = [
508
{ key: 'user-1', title: 'John Doe' },
509
{ key: 'user-2', title: 'Jane Smith' },
510
];
511
512
// β Bad: Non-unique or unstable keys
513
const badTreeData = [
514
{ key: 1, title: 'First' }, // Numbers can conflict
515
{ key: 1, title: 'Second' }, // Duplicate key
516
];
517
518
// β Good: Hierarchical keys for complex structures
519
const hierarchicalData = [
520
{
521
key: 'department-engineering',
522
title: 'Engineering',
523
children: [
524
{ key: 'team-frontend', title: 'Frontend Team' },
525
{ key: 'team-backend', title: 'Backend Team' },
526
],
527
},
528
];
529
```