diff --git a/components/menu/MenuDivider.tsx b/components/menu/MenuDivider.tsx index ae93440a87..1441481bec 100644 --- a/components/menu/MenuDivider.tsx +++ b/components/menu/MenuDivider.tsx @@ -10,12 +10,8 @@ export interface MenuDividerProps extends React.HTMLAttributes { dashed?: boolean; } -const MenuDivider: React.FC = ({ - prefixCls: customizePrefixCls, - className, - dashed, - ...restProps -}) => { +const MenuDivider: React.FC = (props) => { + const { prefixCls: customizePrefixCls, className, dashed, ...restProps } = props; const { getPrefixCls } = React.useContext(ConfigContext); const prefixCls = getPrefixCls('menu', customizePrefixCls); diff --git a/components/menu/MenuItem.tsx b/components/menu/MenuItem.tsx index 14d781c254..47e6ac1ee6 100644 --- a/components/menu/MenuItem.tsx +++ b/components/menu/MenuItem.tsx @@ -2,6 +2,7 @@ import classNames from 'classnames'; import type { MenuItemProps as RcMenuItemProps } from 'rc-menu'; import { Item } from 'rc-menu'; import toArray from 'rc-util/lib/Children/toArray'; +import omit from 'rc-util/lib/omit'; import * as React from 'react'; import type { SiderContextProps } from '../layout/Sider'; import { SiderContext } from '../layout/Sider'; @@ -17,15 +18,16 @@ export interface MenuItemProps extends Omit { title?: React.ReactNode; } -export default class MenuItem extends React.Component { - static contextType = MenuContext; - - context: MenuContextProps; - - renderItemChildren(inlineCollapsed: boolean) { - const { prefixCls, firstLevel } = this.context; - const { icon, children } = this.props; - +const MenuItem: React.FC = (props) => { + const { className, children, icon, title, danger } = props; + const { + prefixCls, + firstLevel, + direction, + disableMenuItemTitleTooltip, + inlineCollapsed: isInlineCollapsed, + } = React.useContext(MenuContext); + const renderItemChildren = (inlineCollapsed: boolean) => { const wrapNode = {children}; // inline-collapsed.md demo 依赖 span 来隐藏文字,有 icon 属性,则内部包裹一个 span // ref: https://github.com/ant-design/ant-design/pull/23456 @@ -35,25 +37,16 @@ export default class MenuItem extends React.Component { } } return wrapNode; - } - - renderItem = ({ siderCollapsed }: SiderContextProps) => { - const { prefixCls, firstLevel, inlineCollapsed, direction, disableMenuItemTitleTooltip } = - this.context; - const { className, children } = this.props; - const { title, icon, danger, ...rest } = this.props; - + }; + const renderItem = ({ siderCollapsed }: SiderContextProps) => { let tooltipTitle = title; if (typeof title === 'undefined') { tooltipTitle = firstLevel ? children : ''; } else if (title === false) { tooltipTitle = ''; } - const tooltipProps: TooltipProps = { - title: tooltipTitle, - }; - - if (!siderCollapsed && !inlineCollapsed) { + const tooltipProps: TooltipProps = { title: tooltipTitle }; + if (!siderCollapsed && !isInlineCollapsed) { tooltipProps.title = null; // Reset `open` to fix control mode tooltip display not correct // ref: https://github.com/ant-design/ant-design/issues/16742 @@ -63,7 +56,7 @@ export default class MenuItem extends React.Component { let returnNode = ( { `${prefixCls}-item-icon`, ), })} - {this.renderItemChildren(inlineCollapsed)} + {renderItemChildren(isInlineCollapsed)} ); @@ -97,8 +90,7 @@ export default class MenuItem extends React.Component { return returnNode; }; + return {renderItem}; +}; - render() { - return {this.renderItem}; - } -} +export default MenuItem; diff --git a/components/menu/OverrideContext.tsx b/components/menu/OverrideContext.tsx index 70dd828efe..900feebca5 100644 --- a/components/menu/OverrideContext.tsx +++ b/components/menu/OverrideContext.tsx @@ -15,17 +15,14 @@ export interface OverrideContextProps { const OverrideContext = React.createContext(null); /** @internal Only used for Dropdown component. Do not use this in your production. */ -export const OverrideProvider = ({ - children, - ...restProps -}: OverrideContextProps & { children: React.ReactNode }) => { +export const OverrideProvider: React.FC = ( + props, +) => { + const { children, ...restProps } = props; const override = React.useContext(OverrideContext); - const context = React.useMemo( - () => ({ - ...override, - ...restProps, - }), + const context = React.useMemo( + () => ({ ...override, ...restProps }), [ override, restProps.prefixCls, diff --git a/components/menu/SubMenu.tsx b/components/menu/SubMenu.tsx index 972f19e74b..1ae6b50840 100644 --- a/components/menu/SubMenu.tsx +++ b/components/menu/SubMenu.tsx @@ -3,7 +3,7 @@ import { SubMenu as RcSubMenu, useFullPath } from 'rc-menu'; import omit from 'rc-util/lib/omit'; import * as React from 'react'; import { cloneElement, isValidElement } from '../_util/reactNode'; -import type { MenuTheme } from './MenuContext'; +import type { MenuContextProps, MenuTheme } from './MenuContext'; import MenuContext from './MenuContext'; interface TitleEventEntity { @@ -27,7 +27,7 @@ export interface SubMenuProps { theme?: MenuTheme; } -function SubMenu(props: SubMenuProps) { +const SubMenu: React.FC = (props) => { const { popupClassName, icon, title, theme: customTheme } = props; const context = React.useContext(MenuContext); const { prefixCls, inlineCollapsed, theme: contextTheme, mode } = context; @@ -60,11 +60,8 @@ function SubMenu(props: SubMenuProps) { ); } - const contextValue = React.useMemo( - () => ({ - ...context, - firstLevel: false, - }), + const contextValue = React.useMemo( + () => ({ ...context, firstLevel: false }), [context], ); @@ -84,6 +81,6 @@ function SubMenu(props: SubMenuProps) { /> ); -} +}; export default SubMenu; diff --git a/components/menu/index.tsx b/components/menu/index.tsx index 5c75a65915..14d0a1b53b 100644 --- a/components/menu/index.tsx +++ b/components/menu/index.tsx @@ -21,9 +21,9 @@ export type MenuRef = { interface CompoundedComponent extends React.ForwardRefExoticComponent> { - Divider: typeof MenuDivider; Item: typeof Item; SubMenu: typeof SubMenu; + Divider: typeof MenuDivider; ItemGroup: typeof ItemGroup; } @@ -32,18 +32,17 @@ const Menu = forwardRef((props, ref) => { const context = React.useContext(SiderContext); useImperativeHandle(ref, () => ({ - focus: options => { + menu: menuRef.current, + focus: (options) => { menuRef.current?.focus(options); }, - menu: menuRef.current, })); - return ; }) as CompoundedComponent; -Menu.Divider = MenuDivider; Menu.Item = Item; Menu.SubMenu = SubMenu; +Menu.Divider = MenuDivider; Menu.ItemGroup = ItemGroup; export default Menu; diff --git a/components/menu/menu.tsx b/components/menu/menu.tsx index c98a532687..1600476deb 100644 --- a/components/menu/menu.tsx +++ b/components/menu/menu.tsx @@ -16,7 +16,7 @@ import OverrideContext from './OverrideContext'; import useItems from './hooks/useItems'; import type { ItemType } from './hooks/useItems'; import MenuContext from './MenuContext'; -import type { MenuTheme } from './MenuContext'; +import type { MenuTheme, MenuContextProps } from './MenuContext'; export interface MenuProps extends Omit { theme?: MenuTheme; @@ -131,7 +131,7 @@ const InternalMenu = forwardRef((props, ref) => { } // ======================== Context ========================== - const contextValue = React.useMemo( + const contextValue = React.useMemo( () => ({ prefixCls, inlineCollapsed: mergedInlineCollapsed || false,