Skip to content

Commit 81eafee

Browse files
authored
feat: MenuItem, MenuGroup and SubMenu support ref (#683)
* feat: MenuItem, MenuGroup and SubMenu support ref * docs: add demo * docs: add ref * test: add case * docs: fix demo
1 parent b29c3fc commit 81eafee

File tree

8 files changed

+485
-298
lines changed

8 files changed

+485
-298
lines changed

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ ReactDOM.render(
7272
</tr>
7373
</thead>
7474
<tbody>
75+
<tr>
76+
<td>ref</td>
77+
<td>React.HTMLLIElement</td>
78+
<td></td>
79+
<td>get dom node</td>
80+
</tr>
7581
<tr>
7682
<td>className</td>
7783
<td>String</td>
@@ -294,6 +300,12 @@ ReactDOM.render(
294300
</tr>
295301
</thead>
296302
<tbody>
303+
<tr>
304+
<td>ref</td>
305+
<td>React.HTMLLIElement</td>
306+
<td></td>
307+
<td>get dom node</td>
308+
</tr>
297309
<tr>
298310
<td>popupClassName</td>
299311
<td>String</td>
@@ -397,6 +409,12 @@ none
397409
</tr>
398410
</thead>
399411
<tbody>
412+
<tr>
413+
<td>ref</td>
414+
<td>React.HTMLLIElement</td>
415+
<td></td>
416+
<td>get dom node</td>
417+
</tr>
400418
<tr>
401419
<td>title</td>
402420
<td>String|React.Element</td>

docs/demo/items-ref.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## items-ref
2+
3+
<code src="../examples/items-ref.tsx"></code>

docs/examples/items-ref.tsx

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* eslint no-console:0 */
2+
3+
import React, { useRef } from 'react';
4+
import '../../assets/index.less';
5+
import Menu from '../../src';
6+
7+
export default () => {
8+
const ref1 = useRef();
9+
const ref2 = useRef();
10+
const ref3 = useRef();
11+
const ref4 = useRef();
12+
const ref5 = useRef();
13+
const ref6 = useRef();
14+
const ref7 = useRef();
15+
16+
return (
17+
<>
18+
<button
19+
onClick={() => {
20+
console.log(ref1.current);
21+
console.log(ref2.current);
22+
console.log(ref3.current);
23+
console.log(ref4.current);
24+
console.log(ref5.current);
25+
console.log(ref6.current);
26+
console.log(ref7.current);
27+
}}
28+
>
29+
获取 Ref
30+
</button>
31+
<Menu
32+
items={[
33+
{
34+
// MenuItem
35+
label: 'Top Menu Item',
36+
key: 'top',
37+
ref: ref1,
38+
},
39+
{
40+
// MenuGroup
41+
type: 'group',
42+
label: 'Top Menu Group without children',
43+
ref: ref2,
44+
},
45+
{
46+
// MenuGroup
47+
type: 'group',
48+
label: 'Top Menu Group with children',
49+
ref: ref3,
50+
children: [
51+
{
52+
// MenuItem
53+
label: 'Menu Item 1',
54+
key: 'inner1',
55+
},
56+
{
57+
// Divider
58+
type: 'divider',
59+
},
60+
{
61+
// MenuItem
62+
label: 'Menu Item 2',
63+
key: 'inner2',
64+
ref: ref4,
65+
},
66+
],
67+
},
68+
{
69+
// SubMenu
70+
label: 'SubMenu',
71+
key: 'sub1',
72+
ref: ref5,
73+
children: [
74+
{
75+
// MenuItem
76+
label: 'Menu Item 1-1',
77+
key: 'inner11',
78+
ref: ref6,
79+
},
80+
81+
{
82+
// SubMenu
83+
label: 'SubMenu inner',
84+
key: 'sub1-1',
85+
ref: ref7,
86+
children: [
87+
{
88+
// MenuItem
89+
label: 'Menu Item 111',
90+
key: 'inner1-1-1',
91+
},
92+
],
93+
},
94+
],
95+
},
96+
]}
97+
/>
98+
</>
99+
);
100+
};

src/MenuItem.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { MenuInfo, MenuItemType } from './interface';
1616
import { warnItemProp } from './utils/warnUtil';
1717

1818
export interface MenuItemProps
19-
extends Omit<MenuItemType, 'label' | 'key'>,
19+
extends Omit<MenuItemType, 'label' | 'key'| 'ref'>,
2020
Omit<
2121
React.HTMLAttributes<HTMLLIElement>,
2222
'onClick' | 'onMouseEnter' | 'onMouseLeave' | 'onSelect'

src/MenuItemGroup.tsx

+31-26
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,18 @@ export interface MenuItemGroupProps
1919
warnKey?: boolean;
2020
}
2121

22-
const InternalMenuItemGroup = ({
23-
className,
24-
title,
25-
eventKey,
26-
children,
27-
...restProps
28-
}: MenuItemGroupProps) => {
22+
const InternalMenuItemGroup = React.forwardRef<
23+
HTMLLIElement,
24+
MenuItemGroupProps
25+
>((props, ref) => {
26+
const { className, title, eventKey, children, ...restProps } = props;
2927
const { prefixCls } = React.useContext(MenuContext);
3028

3129
const groupPrefixCls = `${prefixCls}-item-group`;
3230

3331
return (
3432
<li
33+
ref={ref}
3534
role="presentation"
3635
{...restProps}
3736
onClick={e => e.stopPropagation()}
@@ -49,26 +48,32 @@ const InternalMenuItemGroup = ({
4948
</ul>
5049
</li>
5150
);
52-
};
51+
});
5352

54-
export default function MenuItemGroup({
55-
children,
56-
...props
57-
}: MenuItemGroupProps): React.ReactElement {
58-
const connectedKeyPath = useFullPath(props.eventKey);
59-
const childList: React.ReactElement[] = parseChildren(
60-
children,
61-
connectedKeyPath,
62-
);
53+
const MenuItemGroup = React.forwardRef<HTMLLIElement, MenuItemGroupProps>(
54+
(props, ref) => {
55+
const { eventKey, children } = props;
56+
const connectedKeyPath = useFullPath(eventKey);
57+
const childList: React.ReactElement[] = parseChildren(
58+
children,
59+
connectedKeyPath,
60+
);
6361

64-
const measure = useMeasure();
65-
if (measure) {
66-
return (childList as any) as React.ReactElement;
67-
}
62+
const measure = useMeasure();
63+
if (measure) {
64+
return childList as any as React.ReactElement;
65+
}
6866

69-
return (
70-
<InternalMenuItemGroup {...omit(props, ['warnKey'])}>
71-
{childList}
72-
</InternalMenuItemGroup>
73-
);
67+
return (
68+
<InternalMenuItemGroup ref={ref} {...omit(props, ['warnKey'])}>
69+
{childList}
70+
</InternalMenuItemGroup>
71+
);
72+
},
73+
);
74+
75+
if (process.env.NODE_ENV !== 'production') {
76+
MenuItemGroup.displayName = 'MenuItemGroup';
7477
}
78+
79+
export default MenuItemGroup;

0 commit comments

Comments
 (0)