Skip to content

Commit 4893475

Browse files
authored
fix moving an item to the root (#8225)
1 parent 85764ff commit 4893475

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

packages/@react-stately/data/src/useTreeData.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,7 @@ export function useTreeData<T extends object>(options: TreeOptions<T>): TreeData
370370

371371
// If parentKey is null, insert into the root.
372372
if (toParentKey == null) {
373-
// safe to reuse the original map since no node was actually removed, so we just need to update the one moved node
374-
newMap = new Map(originalMap);
375-
newMap.set(movedNode.key, movedNode);
373+
addNode(movedNode, newMap);
376374
return {items: [
377375
...newItems.slice(0, index),
378376
movedNode,
@@ -406,7 +404,7 @@ export function useTreeData<T extends object>(options: TreeOptions<T>): TreeData
406404
parent = nodeMap.get(toParentKey) ?? null;
407405
}
408406
let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);
409-
return moveItems(prevState, keys, parent, toIndex, updateTree);
407+
return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);
410408
});
411409
},
412410
moveAfter(key: Key, keys: Iterable<Key>) {
@@ -423,7 +421,7 @@ export function useTreeData<T extends object>(options: TreeOptions<T>): TreeData
423421
}
424422
let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);
425423
toIndex++;
426-
return moveItems(prevState, keys, parent, toIndex, updateTree);
424+
return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);
427425
});
428426
},
429427
update(oldKey: Key, newValue: T) {
@@ -450,10 +448,11 @@ function moveItems<T extends object>(
450448
toIndex: number,
451449
updateTree: (
452450
items: TreeNode<T>[],
453-
key: Key,
451+
key: Key | null,
454452
update: (node: TreeNode<T>) => TreeNode<T> | null,
455453
originalMap: Map<Key, TreeNode<T>>
456-
) => TreeDataState<T>
454+
) => TreeDataState<T>,
455+
addNode: (node: TreeNode<T>, map: Map<Key, TreeNode<T>>) => void
457456
): TreeDataState<T> {
458457
let {items, nodeMap} = state;
459458

@@ -515,8 +514,9 @@ function moveItems<T extends object>(
515514
let inOrderItems = removedItems.sort((a, b) => inOrderKeys.get(a.key)! > inOrderKeys.get(b.key)! ? 1 : -1);
516515
// If parentKey is null, insert into the root.
517516
if (!toParent || toParent.key == null) {
518-
newMap = new Map(nodeMap);
519-
inOrderItems.forEach(movedNode => newMap.set(movedNode.key, movedNode));
517+
inOrderItems.forEach(movedNode => {
518+
addNode(movedNode, newMap);
519+
});
520520
return {items: [
521521
...newItems.slice(0, toIndex),
522522
...inOrderItems,

packages/@react-stately/data/test/useTreeData.test.js

+38
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,43 @@ describe('useTreeData', function () {
610610
expect(result.current.items[1].children[2]).toBe(
611611
initialResult.items[0].children[2]
612612
);
613+
614+
/*
615+
Expected tree structure after moving 'Stacy' to root:
616+
- Stacy
617+
- David
618+
|-- John
619+
| -- Suzie
620+
|-- Sam
621+
| -- Brad
622+
|-- Jane
623+
*/
624+
let stacyNode = result.current.getItem('Stacy');
625+
expect(stacyNode.parentKey).toBeNull();
626+
expect(stacyNode.children).toHaveLength(0);
627+
expect(stacyNode).toBe(result.current.items[0]);
628+
629+
let davidNode = result.current.getItem('David');
630+
expect(davidNode.parentKey).toBeNull();
631+
expect(davidNode.children.map(c => c.key)).toEqual(['John', 'Sam', 'Jane']);
632+
expect(davidNode).toBe(result.current.items[1]);
633+
634+
let samNode = result.current.getItem('Sam');
635+
expect(samNode.parentKey).toBe('David');
636+
expect(samNode.children.map(c => c.key)).toEqual(['Brad']);
637+
expect(samNode).toBe(result.current.items[1].children[1]);
638+
639+
let bradNode = result.current.getItem('Brad');
640+
expect(bradNode.parentKey).toBe('Sam');
641+
expect(bradNode).toBe(result.current.items[1].children[1].children[0]);
642+
643+
let johnNode = result.current.getItem('John');
644+
expect(johnNode.parentKey).toBe('David');
645+
expect(johnNode).toBe(result.current.items[1].children[0]);
646+
647+
let janeNode = result.current.getItem('Jane');
648+
expect(janeNode.parentKey).toBe('David');
649+
expect(janeNode).toBe(result.current.items[1].children[2]);
613650
});
614651

615652
it('should move an item to a new index within its current parent', function () {
@@ -876,6 +913,7 @@ describe('useTreeData', function () {
876913
result.current.move('Eli', 'David', 1);
877914
});
878915
expect(result.current.items[0].key).toEqual('David');
916+
879917
expect(result.current.items[0].children[0].key).toEqual('John');
880918
expect(result.current.items[0].children[1].key).toEqual('Eli');
881919
expect(result.current.items[1].key).toEqual('Emily');

0 commit comments

Comments
 (0)