Browse Source

refactor(Menu): rewrite CC => FC (#38751)

pull/38851/head
lijianan 2 years ago
committed by GitHub
parent
commit
6a8f5b5765
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      components/menu/MenuDivider.tsx
  2. 48
      components/menu/MenuItem.tsx
  3. 15
      components/menu/OverrideContext.tsx
  4. 13
      components/menu/SubMenu.tsx
  5. 9
      components/menu/index.tsx
  6. 4
      components/menu/menu.tsx

8
components/menu/MenuDivider.tsx

@ -10,12 +10,8 @@ export interface MenuDividerProps extends React.HTMLAttributes<HTMLLIElement> {
dashed?: boolean;
}
const MenuDivider: React.FC<MenuDividerProps> = ({
prefixCls: customizePrefixCls,
className,
dashed,
...restProps
}) => {
const MenuDivider: React.FC<MenuDividerProps> = (props) => {
const { prefixCls: customizePrefixCls, className, dashed, ...restProps } = props;
const { getPrefixCls } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('menu', customizePrefixCls);

48
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<RcMenuItemProps, 'title'> {
title?: React.ReactNode;
}
export default class MenuItem extends React.Component<MenuItemProps> {
static contextType = MenuContext;
context: MenuContextProps;
renderItemChildren(inlineCollapsed: boolean) {
const { prefixCls, firstLevel } = this.context;
const { icon, children } = this.props;
const MenuItem: React.FC<MenuItemProps> = (props) => {
const { className, children, icon, title, danger } = props;
const {
prefixCls,
firstLevel,
direction,
disableMenuItemTitleTooltip,
inlineCollapsed: isInlineCollapsed,
} = React.useContext<MenuContextProps>(MenuContext);
const renderItemChildren = (inlineCollapsed: boolean) => {
const wrapNode = <span className={`${prefixCls}-title-content`}>{children}</span>;
// 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<MenuItemProps> {
}
}
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<MenuItemProps> {
let returnNode = (
<Item
{...rest}
{...omit(props, ['title', 'icon', 'danger'])}
className={classNames(
{
[`${prefixCls}-item-danger`]: danger,
@ -79,7 +72,7 @@ export default class MenuItem extends React.Component<MenuItemProps> {
`${prefixCls}-item-icon`,
),
})}
{this.renderItemChildren(inlineCollapsed)}
{renderItemChildren(isInlineCollapsed)}
</Item>
);
@ -97,8 +90,7 @@ export default class MenuItem extends React.Component<MenuItemProps> {
return returnNode;
};
return <SiderContext.Consumer>{renderItem}</SiderContext.Consumer>;
};
render() {
return <SiderContext.Consumer>{this.renderItem}</SiderContext.Consumer>;
}
}
export default MenuItem;

15
components/menu/OverrideContext.tsx

@ -15,17 +15,14 @@ export interface OverrideContextProps {
const OverrideContext = React.createContext<OverrideContextProps | null>(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<OverrideContextProps & { children: React.ReactNode }> = (
props,
) => {
const { children, ...restProps } = props;
const override = React.useContext(OverrideContext);
const context = React.useMemo(
() => ({
...override,
...restProps,
}),
const context = React.useMemo<OverrideContextProps>(
() => ({ ...override, ...restProps }),
[
override,
restProps.prefixCls,

13
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<SubMenuProps> = (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<MenuContextProps>(
() => ({ ...context, firstLevel: false }),
[context],
);
@ -84,6 +81,6 @@ function SubMenu(props: SubMenuProps) {
/>
</MenuContext.Provider>
);
}
};
export default SubMenu;

9
components/menu/index.tsx

@ -21,9 +21,9 @@ export type MenuRef = {
interface CompoundedComponent
extends React.ForwardRefExoticComponent<MenuProps & React.RefAttributes<MenuRef>> {
Divider: typeof MenuDivider;
Item: typeof Item;
SubMenu: typeof SubMenu;
Divider: typeof MenuDivider;
ItemGroup: typeof ItemGroup;
}
@ -32,18 +32,17 @@ const Menu = forwardRef<MenuRef, MenuProps>((props, ref) => {
const context = React.useContext(SiderContext);
useImperativeHandle(ref, () => ({
focus: options => {
menu: menuRef.current,
focus: (options) => {
menuRef.current?.focus(options);
},
menu: menuRef.current,
}));
return <InternalMenu ref={menuRef} {...props} {...context} />;
}) as CompoundedComponent;
Menu.Divider = MenuDivider;
Menu.Item = Item;
Menu.SubMenu = SubMenu;
Menu.Divider = MenuDivider;
Menu.ItemGroup = ItemGroup;
export default Menu;

4
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<RcMenuProps, 'items'> {
theme?: MenuTheme;
@ -131,7 +131,7 @@ const InternalMenu = forwardRef<RcMenuRef, InternalMenuProps>((props, ref) => {
}
// ======================== Context ==========================
const contextValue = React.useMemo(
const contextValue = React.useMemo<MenuContextProps>(
() => ({
prefixCls,
inlineCollapsed: mergedInlineCollapsed || false,

Loading…
Cancel
Save