You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// The `treeWalker` function runs only on tree re-build which is performed
77
83
// whenever the `treeWalker` prop is changed.
78
84
function*treeWalker() {
79
-
// Step [1]: Define the root node of our tree.
80
-
yieldgetNodeData(rootNode, 0);
85
+
// Step [1]: Define the root node of our tree. There can be one or
86
+
// multiple nodes.
87
+
for (let i =0; i <treeNodes.length; i++) {
88
+
yieldgetNodeData(treeNodes[i], 0);
89
+
}
81
90
82
91
while (true) {
83
92
// Step [2]: Get the parent component back. It will be the object
@@ -230,7 +239,7 @@ The rules object has the following shape:
230
239
-`open: boolean` - this rule changes the openness state for the owner node only (subtree nodes are not affected).
231
240
-`subtreeCallback(node: object, ownerNode: object): void` - this callback runs against each node in the subtree of the owner node (including the owner node as well). It receives the subtree node and the owner node. Changing any property of the subtree node will affect the node state and how it will be displayed (e.g. if you change the node openness state it will be displayed according to the changed state).
232
241
233
-
The order of rules matters. If you specify the child node rules before the parent node rules, and that rules affect the same property, the parent node subtreeWalker will override that property. So if you want to override parent's rules, place children rules after the parent's.
242
+
The order of rules matters. If you specify the child node rules before the parent node rules, and that rules affect the same property, the parent node `subtreeWalker` will override that property. So if you want to override parent's rules, place children rules after the parent's.
234
243
235
244
The type of the node objects received by `subtreeCallback` is `FixedSizeNodePublicState`. See the [types description](#types) below.
// The `treeWalker` function runs only on tree re-build which is performed
345
354
// whenever the `treeWalker` prop is changed.
346
355
function*treeWalker() {
347
-
// Step [1]: Define the root node of our tree.
348
-
yieldgetNodeData(rootNode, 0);
356
+
// Step [1]: Define the root node of our tree. There can be yielded one or
357
+
// multiple nodes.
358
+
yieldgetNodeData(tree, 0);
349
359
350
360
while (true) {
351
361
// Step [2]: Get the parent component back. It will be the object
@@ -436,9 +446,9 @@ All types in this section are the extended variants of [`FixedSizeTree` types](#
436
446
437
447
The `treeWalker` algorithm works in the following way. During the execution, the `treeWalker` function sends a bunch of objects to the tree component which builds an internal representation of the tree. However, for it, the specific order of yieldings should be performed.
438
448
439
-
1. The first yielding is always the root node. It will be the foundation of the whole tree.
449
+
1. The first yielding is always root nodes. They will be the foundation of the whole tree.
440
450
2. Now start a loop where you will receive the parent node and yield all the children of it.
441
-
3. The first yielding of loop iteration should yield an `undefined`. In exchange, you will receive a node for which you should yield all the children in the same way you've done with the root.
451
+
3. The first yielding of loop iteration should yield an `undefined`. In exchange, you will receive a node for which you should yield all the children in the same way you've done with the root ones.
442
452
4. When all the children are yielded, and the new iteration of loop is started, you yield `undefined` again and in exchange receive the next node. It may be:
443
453
- a child node if the previous node has children;
444
454
- a sibling node if it has siblings;
@@ -467,3 +477,138 @@ function* treeWalker() {
467
477
}
468
478
}
469
479
```
480
+
481
+
## Migrating v2 -> v3
482
+
483
+
If you use `react-vtree` of version 2, it is preferable migrate to the version 3. The third version is quite different under the hood and provides way more optimized approach to the initial tree building and tree openness state change. The most obvious it becomes if you have a giant tree (with about 1 million of nodes).
484
+
485
+
To migrate to the new version, you have to do the following steps.
486
+
487
+
### 1. Migrate `treeWalker`
488
+
489
+
The `treeWalker` was and is the heart of the `react-vtree`. However, now it looks a bit different.
490
+
491
+
Old `treeWalker` worked for both initial tree building and changing node openness state:
492
+
493
+
```js
494
+
function*treeWalker( refresh
495
+
) {
496
+
conststack= [];
497
+
498
+
stack.push({
499
+
nestingLevel:0,
500
+
node: rootNode,
501
+
});
502
+
503
+
// Go through all the nodes adding children to the stack and removing them
504
+
// when they are processed.
505
+
while (stack.length!==0) {
506
+
const {node, nestingLevel} =stack.pop();
507
+
constid=node.id.toString();
508
+
509
+
// Receive the openness state of the node we are working with
510
+
constisOpened=yield refresh
511
+
? {
512
+
id,
513
+
isLeaf:node.children.length===0,
514
+
isOpenByDefault:true,
515
+
name:node.name,
516
+
nestingLevel,
517
+
}
518
+
: id;
519
+
520
+
if (node.children.length!==0&& isOpened) {
521
+
for (let i =node.children.length-1; i >=0; i--) {
522
+
stack.push({
523
+
nestingLevel: nestingLevel +1,
524
+
node:node.children[i],
525
+
});
526
+
}
527
+
}
528
+
}
529
+
}
530
+
```
531
+
532
+
The new `treeWalker` is only for the tree building. The `Tree` component builds and preserves the tree structure internally. See the full description [above](#treewalker-algorithm).
533
+
534
+
```js
535
+
// This function prepares an object for yielding. We can yield an object
536
+
// that has `data` object with `id` and `isOpenByDefault` fields.
537
+
// We can also add any other data here.
538
+
constgetNodeData= (node, nestingLevel) => ({
539
+
data: {
540
+
id:node.id.toString(),
541
+
isLeaf:node.children.length===0,
542
+
isOpenByDefault:true,
543
+
name:node.name,
544
+
nestingLevel,
545
+
},
546
+
nestingLevel,
547
+
node,
548
+
});
549
+
550
+
function*treeWalker() {
551
+
// Here we send root nodes to the component.
552
+
for (let i =0; i <rootNodes.length; i++) {
553
+
yieldgetNodeData(rootNodes[i], 0);
554
+
}
555
+
556
+
while (true) {
557
+
// Here we receive an object we created via getNodeData function
558
+
// and yielded before. All we need here is to describe its children
559
+
// in the same way we described the root nodes.
560
+
constparentMeta=yield;
561
+
562
+
for (let i =0; i <parentMeta.node.children.length; i++) {
563
+
yieldgetNodeData(
564
+
parentMeta.node.children[i],
565
+
parentMeta.nestingLevel+1,
566
+
);
567
+
}
568
+
}
569
+
}
570
+
```
571
+
572
+
### 2. Migrate tree components
573
+
574
+
Components haven't been changed a lot but you may want to add new features like:
The `recomputeTree` method now receives a list of nodes to change (previously, it was an `opennessState` object). See the full description [above](#async-recomputetreestate-void).
583
+
584
+
The most important change is the introduction of the `subtreeCallback`. It is a function that will be applied to each node in the subtree of the specified node. Among other useful things it also allows imitating the behavior of old `useDefaultOpenness` and `useDefaultHeight` options.
0 commit comments