Skip to content

Commit c9a0d36

Browse files
fix: moving a root item after itself does not move the item (#8436)
* fix: moving a root item before itself does not move the item * Update packages/@react-stately/data/src/useTreeData.ts --------- Co-authored-by: Robert Snow <[email protected]> Co-authored-by: Robert Snow <[email protected]>
1 parent dfdb167 commit c9a0d36

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,9 @@ function moveItems<T extends object>(
502502
newMap = nextMap;
503503
}
504504
// decrement the index if the child being removed is in the target parent and before the target index
505-
if (child.parentKey === toParent?.key
505+
// the root node is special, it is null, and will not have a key, however, a parentKey can still point to it
506+
if ((child.parentKey === toParent
507+
|| child.parentKey === toParent?.key)
506508
&& keyArray.includes(child.key)
507509
&& (toParent?.children ? toParent.children.indexOf(child) : items.indexOf(child)) < originalToIndex) {
508510
toIndex--;

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,4 +1115,74 @@ describe('useTreeData', function () {
11151115
expect(result.current.items[1].key).toEqual('Emily');
11161116
expect(result.current.items.length).toEqual(2);
11171117
});
1118+
1119+
it('should not move the item when moving it before itself', () => {
1120+
const initialItems = [...initial, {name: 'Emily'}, {name: 'Eli'}];
1121+
1122+
let {result} = renderHook(() => useTreeData({initialItems, getChildren, getKey}));
1123+
let initialResult = result.current;
1124+
1125+
act(() => {
1126+
result.current.moveBefore('David', ['David']);
1127+
});
1128+
expect(result.current.items).toEqual(initialResult.items);
1129+
1130+
act(() => {
1131+
result.current.moveBefore('David', ['David', 'Eli']);
1132+
});
1133+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1134+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1135+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1136+
1137+
act(() => {
1138+
result.current.moveBefore('John', ['John']);
1139+
});
1140+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1141+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1142+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1143+
expect(result.current.items[0].children).toEqual(initialResult.items[0].children);
1144+
1145+
act(() => {
1146+
result.current.moveBefore('Jane', ['Sam', 'Jane']);
1147+
});
1148+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1149+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1150+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1151+
expect(result.current.items[0].children).toEqual(initialResult.items[0].children);
1152+
});
1153+
1154+
it('should not move the item when moving it after itself', () => {
1155+
const initialItems = [...initial, {name: 'Emily'}, {name: 'Eli'}];
1156+
1157+
let {result} = renderHook(() => useTreeData({initialItems, getChildren, getKey}));
1158+
let initialResult = result.current;
1159+
1160+
act(() => {
1161+
result.current.moveAfter('David', ['David']);
1162+
});
1163+
expect(result.current.items).toEqual(initialResult.items);
1164+
1165+
act(() => {
1166+
result.current.moveAfter('David', ['David', 'Eli']);
1167+
});
1168+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1169+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1170+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1171+
1172+
act(() => {
1173+
result.current.moveAfter('John', ['John']);
1174+
});
1175+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1176+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1177+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1178+
expect(result.current.items[0].children).toEqual(initialResult.items[0].children);
1179+
1180+
act(() => {
1181+
result.current.moveAfter('Jane', ['Sam', 'Jane']);
1182+
});
1183+
expect(result.current.items[0]).toEqual(initialResult.items[0]);
1184+
expect(result.current.items[1]).toEqual(initialResult.items[2]);
1185+
expect(result.current.items[2]).toEqual(initialResult.items[1]);
1186+
expect(result.current.items[0].children).toEqual(initialResult.items[0].children);
1187+
});
11181188
});

0 commit comments

Comments
 (0)