diff --git a/src/Icon.tsx b/src/Icon.tsx index 19ab0906..296b109a 100644 --- a/src/Icon.tsx +++ b/src/Icon.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { isReactRenderable } from '@rc-component/util'; import type { RenderIconInfo, RenderIconType } from './interface'; export interface IconProps { @@ -19,10 +20,10 @@ export default function Icon({ icon, props, children }: IconProps) { iconNode = React.createElement(icon as any, { ...props, }); - } else if (typeof icon !== "boolean") { + } else if (typeof icon !== 'boolean') { // Compatible for origin definition iconNode = icon as React.ReactElement; } - return iconNode || children || null; + return isReactRenderable(iconNode) ? iconNode : children || null; } diff --git a/src/MenuItem.tsx b/src/MenuItem.tsx index cda3d0c4..88f6d351 100644 --- a/src/MenuItem.tsx +++ b/src/MenuItem.tsx @@ -1,6 +1,6 @@ import { clsx } from 'clsx'; import Overflow from '@rc-component/overflow'; -import { omit, warning, KeyCode, useComposeRef } from '@rc-component/util'; +import { isReactRenderable, omit, warning, KeyCode, useComposeRef } from '@rc-component/util'; import * as React from 'react'; import { useMenuId } from './context/IdContext'; import { MenuContext } from './context/MenuContext'; @@ -154,7 +154,7 @@ const InternalMenuItem = React.forwardRef((props: MenuItemProps, ref: React.Ref< }; // ============================= Icon ============================= - const mergedItemIcon = itemIcon || contextItemIcon; + const mergedItemIcon = isReactRenderable(itemIcon) ? itemIcon : contextItemIcon; // ============================ Active ============================ const { active, ...activeProps } = useActive( diff --git a/tests/renderability.test.tsx b/tests/renderability.test.tsx new file mode 100644 index 00000000..f88e3136 --- /dev/null +++ b/tests/renderability.test.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Menu from '../src'; + +describe('icon renderability', () => { + it('renders a global zero item icon', () => { + const { container } = render(); + expect(container.querySelector('.rc-menu-item').textContent).toBe('A0'); + }); + + it('lets a zero item icon override the global icon', () => { + const { container } = render( + , + ); + expect(container.querySelector('.rc-menu-item').textContent).toBe('A0'); + }); + + it.each([0, false, null])('preserves the expand icon %s', expandIcon => { + const { container } = render( + , + ); + expect(container.querySelector('.rc-menu-submenu-title').textContent).toBe( + expandIcon === 0 ? 'A0' : 'A', + ); + expect(container.querySelector('.rc-menu-submenu-arrow')).toBeNull(); + }); +});