Skip to content

Commit 68403fe

Browse files
authored
Fix useTreeData error and types (#6923)
* Fix useTreeData error and types
1 parent 98e21e1 commit 68403fe

File tree

3 files changed

+92
-7
lines changed

3 files changed

+92
-7
lines changed

packages/@react-spectrum/listbox/stories/ListBox.stories.tsx

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Cut from '@spectrum-icons/workflow/Cut';
2222
import Delete from '@spectrum-icons/workflow/Delete';
2323
import {FocusScope} from '@react-aria/focus';
2424
import {Item, ListBox, Section} from '../';
25+
import {Key} from '@react-types/shared';
2526
import {Label} from '@react-spectrum/label';
2627
import Paste from '@spectrum-icons/workflow/Paste';
2728
import React, {useRef, useState} from 'react';
@@ -943,11 +944,12 @@ export function FocusExample(args = {}) {
943944

944945
let [dialog, setDialog] = useState(null);
945946
let ref = useRef(null);
947+
946948
return (
947949
<FocusScope>
948950
<Flex direction={'column'}>
949951
<ActionGroup marginBottom={8} onAction={action => setDialog({action})}>
950-
{tree.selectedKeys.size > 0 &&
952+
{(tree.selectedKeys.size > 0) &&
951953
<Item key="bulk-delete" aria-label="Delete selected items"><Delete /></Item>
952954
}
953955
</ActionGroup>
@@ -961,7 +963,11 @@ export function FocusExample(args = {}) {
961963
aria-labelledby="label"
962964
items={tree.items}
963965
selectedKeys={tree.selectedKeys}
964-
onSelectionChange={tree.setSelectedKeys}
966+
onSelectionChange={(keys) => {
967+
if (keys !== 'all') {
968+
tree.setSelectedKeys(keys);
969+
}
970+
}}
965971
selectionMode="multiple"
966972
{...args}>
967973
{item => item.children.length && (
@@ -1043,3 +1049,68 @@ export const WithAvatars = {
10431049
</StoryDecorator>
10441050
)]
10451051
};
1052+
1053+
interface Iitem {
1054+
name: string,
1055+
items?: Array<Iitem> | null
1056+
}
1057+
1058+
export function WithTreeData() {
1059+
let tree = useTreeData<Iitem>({
1060+
initialItems: [
1061+
{
1062+
name: 'People',
1063+
items: [
1064+
{name: 'David'},
1065+
{name: 'Sam'},
1066+
{name: 'Jane'}
1067+
]
1068+
},
1069+
{
1070+
name: 'Animals',
1071+
items: [
1072+
{name: 'Aardvark'},
1073+
{name: 'Kangaroo'},
1074+
{name: 'Snake', items: null}
1075+
]
1076+
}
1077+
],
1078+
initialSelectedKeys: ['Sam', 'Kangaroo'],
1079+
getKey: item => item.name,
1080+
getChildren: item => item.items || []
1081+
});
1082+
return (
1083+
<ListBox
1084+
width="250px"
1085+
height={400}
1086+
aria-label="List organisms"
1087+
items={tree.items}
1088+
selectedKeys={tree.selectedKeys}
1089+
selectionMode="multiple"
1090+
onSelectionChange={(keys) => {
1091+
if (keys === 'all') {
1092+
tree.setSelectedKeys(new Set(tree.items.reduce((acc, item) => {
1093+
acc.push(item.key);
1094+
function traverse(children) {
1095+
if (children) {
1096+
children.forEach(child => {
1097+
acc.push(child.key);
1098+
traverse(child.children);
1099+
});
1100+
}
1101+
}
1102+
traverse(item.children);
1103+
return acc;
1104+
}, [] as Key[])));
1105+
} else {
1106+
tree.setSelectedKeys(keys);
1107+
}
1108+
}}>
1109+
{node => (
1110+
<Section title={node.value.name} items={node.children}>
1111+
{node => <Item>{node.value.name}</Item>}
1112+
</Section>
1113+
)}
1114+
</ListBox>
1115+
);
1116+
}

packages/@react-stately/data/docs/useTreeData.mdx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ as the unique key for that item, and the `items` property as the children. In ad
6262
for the listbox, which will automatically be updated when items are removed from the tree.
6363

6464
```tsx
65-
let tree = useTreeData({
65+
interface Iitem {
66+
name: string;
67+
items?: Array<Iitem>;
68+
}
69+
70+
let tree = useTreeData<Iitem>({
6671
initialItems: [
6772
{
6873
name: 'People',
@@ -83,13 +88,19 @@ let tree = useTreeData({
8388
],
8489
initialSelectedKeys: ['Sam', 'Kangaroo'],
8590
getKey: item => item.name,
86-
getChildren: item => item.items
91+
getChildren: item => item.items || []
8792
});
8893

8994
<ListBox
95+
aria-label="List organisms"
9096
items={tree.items}
97+
selectionMode="multiple"
9198
selectedKeys={tree.selectedKeys}
92-
onSelectionChange={tree.setSelectedKeys}>
99+
onSelectionChange={(keys) => {
100+
if (keys !== 'all') {
101+
tree.setSelectedKeys(keys);
102+
}
103+
}}>
93104
{node =>
94105
<Section title={node.value.name} items={node.children}>
95106
{node => <Item>{node.value.name}</Item>}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function useTreeData<T extends object>(options: TreeOptions<T>): TreeData
123123
let {
124124
initialItems = [],
125125
initialSelectedKeys,
126-
getKey = (item: any) => item.id || item.key,
126+
getKey = (item: any) => item.id ?? item.key,
127127
getChildren = (item: any) => item.children
128128
} = options;
129129

@@ -133,7 +133,10 @@ export function useTreeData<T extends object>(options: TreeOptions<T>): TreeData
133133

134134
let [selectedKeys, setSelectedKeys] = useState(new Set<Key>(initialSelectedKeys || []));
135135

136-
function buildTree(initialItems: T[] = [], map: Map<Key, TreeNode<T>>, parentKey?: Key | null) {
136+
function buildTree(initialItems: T[] | null = [], map: Map<Key, TreeNode<T>>, parentKey?: Key | null) {
137+
if (initialItems == null) {
138+
initialItems = [];
139+
}
137140
return {
138141
items: initialItems.map(item => {
139142
let node: TreeNode<T> = {

0 commit comments

Comments
 (0)