Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ ReactDOM.render(
</tr>
<tr>
<td>onSelect</td>
<td>function({key:String, item:ReactComponent, domEvent:Event, selectedKeys:String[]})</td>
<td>function({key:String, item:ReactComponent, domEvent:Event, selectedKeys:String[], info:{item:MenuItemInfo}})</td>
<th></th>
<td>called when select a menu item</td>
</tr>
<tr>
<td>onClick</td>
<td>function({key:String, item:ReactComponent, domEvent:Event, keyPath: String[]})</td>
<td>function({key:String, item:ReactComponent, domEvent:Event, keyPath: String[], info:{item:MenuItemInfo}})</td>
<th></th>
<td>called when click a menu item</td>
</tr>
Expand Down
15 changes: 14 additions & 1 deletion src/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import PrivateContext from './context/PrivateContext';
import useActive from './hooks/useActive';
import useDirectionStyle from './hooks/useDirectionStyle';
import Icon from './Icon';
import type { MenuInfo, MenuItemType } from './interface';
import type { MenuInfo, MenuItemInfo, MenuItemType } from './interface';
import { warnItemProp } from './utils/warnUtil';

export interface MenuItemProps
Expand All @@ -32,6 +32,9 @@ export interface MenuItemProps

/** @deprecated No place to use this. Should remove */
attribute?: Record<string, string>;

/** @private Origin item config from items prop */
info?: { item: MenuItemInfo };
}

// Since Menu event provide the `info.item` which point to the MenuItem node instance.
Expand Down Expand Up @@ -77,6 +80,7 @@ const InternalMenuItem = React.forwardRef((props: MenuItemProps, ref: React.Ref<
disabled,
itemIcon,
children,
info: propsInfo,

// Aria
role,
Expand Down Expand Up @@ -133,12 +137,21 @@ const InternalMenuItem = React.forwardRef((props: MenuItemProps, ref: React.Ref<
const getEventInfo = (
e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
): MenuInfo => {
// If propsInfo exists (items mode), use it; otherwise build from props (children mode)
const infoItem: MenuItemInfo = propsInfo?.item || {
key: eventKey || '',
label: children,
itemIcon,
extra: props.extra,
};

return {
key: eventKey,
// Note: For legacy code is reversed which not like other antd component
keyPath: [...connectedKeys].reverse(),
item: legacyMenuItemRef.current,
domEvent: e,
info: propsInfo || { item: infoItem },
};
};

Expand Down
9 changes: 9 additions & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ export interface MenuItemType extends ItemSharedProps {
onClick?: MenuClickEventHandler;
}

/** Info item type passed to onSelect/onClick callbacks, excluding event handlers */
export type MenuItemInfo = {
label?: React.ReactNode;
itemIcon?: RenderIconType;
extra?: React.ReactNode;
key: React.Key;
};

export interface MenuItemGroupType extends ItemSharedProps {
type: 'group';

Expand Down Expand Up @@ -99,6 +107,7 @@ export interface MenuInfo {
/** @deprecated This will not support in future. You should avoid to use this */
item: React.ReactInstance;
domEvent: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>;
info: { item: MenuItemInfo };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

叫 itemData 吧,不要 info.info.item 这个有点太恶心了。然后这个 PR 把 deprecated item 给删了。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已经修改了

}

export interface MenuTitleInfo {
Expand Down
7 changes: 6 additions & 1 deletion src/utils/nodeUtil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ function convertItemsToNodes(
const hasExtra = !!extra || extra === 0;

return (
<MergedMenuItem key={mergedKey} {...restProps} extra={extra}>
<MergedMenuItem
key={mergedKey}
{...restProps}
extra={extra}
info={{ item: { label, key: mergedKey, itemIcon: restProps?.itemIcon, extra } }}
>
{hasExtra ? (
<>
<span className={`${prefixCls}-item-label`}>{label}</span>
Expand Down
73 changes: 73 additions & 0 deletions tests/MenuItem.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,79 @@ describe('MenuItem', () => {
});
});

describe('info.item in event', () => {
it('should pass info.item in onSelect and onClick with children', () => {
const onSelect = jest.fn();
const onClick = jest.fn();
const { container } = render(
<Menu onSelect={onSelect} onClick={onClick} selectable>
<MenuItem key="1">Menu Item</MenuItem>
</Menu>,
);

fireEvent.click(container.querySelector('.rc-menu-item')!);
expect(onSelect).toHaveBeenCalledWith(
expect.objectContaining({
key: '1',
info: expect.objectContaining({
item: expect.objectContaining({
key: '1',
label: 'Menu Item',
}),
}),
}),
);
expect(onClick).toHaveBeenCalledWith(
expect.objectContaining({
key: '1',
info: expect.objectContaining({
item: expect.objectContaining({
key: '1',
label: 'Menu Item',
}),
}),
}),
);
});

it('should pass info.item in onSelect and onClick with items', () => {
const onSelect = jest.fn();
const onClick = jest.fn();
const { container } = render(
<Menu
onSelect={onSelect}
onClick={onClick}
selectable
items={[{ key: '1', label: 'Menu Item' }]}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里多加一个 foo: 123 然后下面测试里补充一起对比存在

/>,
);

fireEvent.click(container.querySelector('.rc-menu-item')!);
expect(onSelect).toHaveBeenCalledWith(
expect.objectContaining({
key: '1',
info: expect.objectContaining({
item: expect.objectContaining({
key: '1',
label: 'Menu Item',
}),
}),
}),
);
expect(onClick).toHaveBeenCalledWith(
expect.objectContaining({
key: '1',
info: expect.objectContaining({
item: expect.objectContaining({
key: '1',
label: 'Menu Item',
}),
}),
}),
);
});
});

describe('overwrite default role', () => {
it('should set role to none if null', () => {
const { container } = render(
Expand Down
Loading