Skip to content

Commit e3c50a0

Browse files
committed
chore: Use const to support generic
1 parent 0a89ef8 commit e3c50a0

File tree

4 files changed

+72
-61
lines changed

4 files changed

+72
-61
lines changed

src/generate.tsx

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ export default function generate(config: {
162162

163163
RefSelect.displayName = 'Select';
164164

165+
// =================================================================================
166+
// = Tree =
167+
// =================================================================================
165168
const RefTreeSelect = React.forwardRef<RefSelectProps, TreeSelectProps>((props, ref) => {
166169
const {
167170
multiple,
@@ -198,15 +201,6 @@ export default function generate(config: {
198201
const treeConduction = treeCheckable && !treeCheckStrictly;
199202
const mergedLabelInValue = treeCheckStrictly || labelInValue;
200203

201-
// ========================== Ref ==========================
202-
const selectRef = React.useRef<RefSelectProps>(null);
203-
204-
React.useImperativeHandle(ref, () => ({
205-
scrollTo: selectRef.current.scrollTo,
206-
focus: selectRef.current.focus,
207-
blur: selectRef.current.blur,
208-
}));
209-
210204
// ======================= Tree Data =======================
211205
// Legacy both support `label` or `title` if not set.
212206
// We have to fallback to function to handle this
@@ -242,6 +236,18 @@ export default function generate(config: {
242236
return { keyEntities: null };
243237
}, [mergedTreeData, treeCheckable, treeCheckStrictly]);
244238

239+
// ========================== Ref ==========================
240+
const selectRef = React.useRef<RefSelectProps>(null);
241+
242+
React.useImperativeHandle(ref, () => ({
243+
scrollTo: selectRef.current.scrollTo,
244+
focus: selectRef.current.focus,
245+
blur: selectRef.current.blur,
246+
247+
/** @private Internal usage. It's save to remove if `rc-cascader` not use it any longer */
248+
getEntityByValue,
249+
}));
250+
245251
// ========================= Value =========================
246252
const [value, setValue] = useMergedState<DefaultValueType>(props.defaultValue, {
247253
value: props.value,
@@ -569,32 +575,24 @@ export default function generate(config: {
569575
);
570576
});
571577

572-
// Use class component since typescript not support generic
573-
// by `forwardRef` with function component yet.
574-
return class TreeSelect<ValueType = DefaultValueType> extends React.Component<
575-
TreeSelectProps<ValueType>,
576-
{}
577-
> {
578-
static TreeNode = TreeNode;
579-
580-
static SHOW_ALL: typeof SHOW_ALL = SHOW_ALL;
581-
582-
static SHOW_PARENT: typeof SHOW_PARENT = SHOW_PARENT;
583-
584-
static SHOW_CHILD: typeof SHOW_CHILD = SHOW_CHILD;
585-
586-
selectRef = React.createRef<RefSelectProps>();
587-
588-
focus = () => {
589-
this.selectRef.current.focus();
590-
};
578+
// =================================================================================
579+
// = Generic =
580+
// =================================================================================
581+
const TreeSelect = RefTreeSelect as any as (<ValueType = DefaultValueType>(
582+
props: React.PropsWithChildren<TreeSelectProps<ValueType>> & {
583+
ref?: React.Ref<RefSelectProps>;
584+
},
585+
) => React.ReactElement) & {
586+
TreeNode: typeof TreeNode;
587+
SHOW_ALL: typeof SHOW_ALL;
588+
SHOW_PARENT: typeof SHOW_PARENT;
589+
SHOW_CHILD: typeof SHOW_CHILD;
590+
};
591591

592-
blur = () => {
593-
this.selectRef.current.blur();
594-
};
592+
TreeSelect.TreeNode = TreeNode;
593+
TreeSelect.SHOW_ALL = SHOW_ALL;
594+
TreeSelect.SHOW_PARENT = SHOW_PARENT;
595+
TreeSelect.SHOW_CHILD = SHOW_CHILD;
595596

596-
render() {
597-
return <RefTreeSelect ref={this.selectRef} {...this.props} />;
598-
}
599-
};
597+
return TreeSelect;
600598
}

src/interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface FlattenDataNode {
5050
data: DataNode;
5151
key: Key;
5252
level: number;
53+
parent?: FlattenDataNode;
5354
}
5455

5556
export interface SimpleModeConfig {

src/utils/valueUtil.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,32 @@ export function flattenOptions(options: DataNode[]): FlattenDataNode[] {
8686

8787
const flattenList = flattenTreeData(fillKey(options), true);
8888

89-
return flattenList.map((node) => ({
90-
key: node.data.key,
91-
data: node.data,
92-
level: getLevel(node),
93-
}));
89+
const cacheMap = new Map<React.Key, FlattenDataNode>();
90+
const flattenDateNodeList: (FlattenDataNode & { parentKey?: React.Key })[] = flattenList.map(
91+
(node) => {
92+
const { data } = node;
93+
const { key } = data;
94+
95+
const flattenNode = {
96+
key,
97+
data,
98+
level: getLevel(node),
99+
parentKey: node.parent?.data.key,
100+
};
101+
102+
cacheMap.set(key, flattenNode);
103+
104+
return flattenNode;
105+
},
106+
);
107+
108+
// Fill parent
109+
flattenDateNodeList.forEach((flattenNode) => {
110+
// eslint-disable-next-line no-param-reassign
111+
flattenNode.parent = cacheMap.get(flattenNode.parentKey);
112+
});
113+
114+
return flattenDateNodeList;
94115
}
95116

96117
function getDefaultFilterOption(optionFilterProp: string) {

tests/shared/focusTest.js

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,45 +18,36 @@ export default function focusTest(mode) {
1818
it('focus()', () => {
1919
const handleFocus = jest.fn();
2020
const treeData = [{ key: '0', value: '0', title: '0 label' }];
21-
const wrapper = mount(
22-
<TreeSelect
23-
{...{ [mode]: true }}
24-
onFocus={handleFocus}
25-
treeData={treeData}
26-
/>,
21+
const treeRef = React.createRef();
22+
23+
mount(
24+
<TreeSelect {...{ [mode]: true }} onFocus={handleFocus} treeData={treeData} ref={treeRef} />,
2725
{ attachTo: container },
2826
);
2927

30-
wrapper.instance().focus();
28+
treeRef.current.focus();
3129
expect(handleFocus).toHaveBeenCalled();
3230
});
3331

3432
it('blur()', () => {
3533
const handleBlur = jest.fn();
3634
const treeData = [{ key: '0', value: '0', title: '0 label' }];
37-
const wrapper = mount(
38-
<TreeSelect
39-
{...{ [mode]: true }}
40-
onBlur={handleBlur}
41-
treeData={treeData}
42-
/>,
35+
const treeRef = React.createRef();
36+
37+
mount(
38+
<TreeSelect {...{ [mode]: true }} onBlur={handleBlur} treeData={treeData} ref={treeRef} />,
4339
{ attachTo: container },
4440
);
45-
wrapper.instance().focus();
46-
wrapper.instance().blur();
41+
treeRef.current.focus();
42+
treeRef.current.blur();
4743
expect(handleBlur).toHaveBeenCalled();
4844
});
4945

5046
it('autoFocus', () => {
5147
const handleFocus = jest.fn();
5248
const treeData = [{ key: '0', value: '0', title: '0 label' }];
5349
mount(
54-
<TreeSelect
55-
{...{ [mode]: true }}
56-
autoFocus
57-
onFocus={handleFocus}
58-
treeData={treeData}
59-
/>,
50+
<TreeSelect {...{ [mode]: true }} autoFocus onFocus={handleFocus} treeData={treeData} />,
6051
{ attachTo: container },
6152
);
6253
expect(handleFocus).toHaveBeenCalled();

0 commit comments

Comments
 (0)