I'm trying to build a dynamic menu component in antd using typescript.
I have checked this solution in javascript React Antd dynamic dropdown menu.
But when using typescript, it shows that item
only have attribute className, key, style
.
So how could i do it in ts?
Here's my code and it failes to build at icon={item?.icon}
and {item?.label}
.
import type { MenuProps } from 'antd';
function CustomAppBarMenu() {
const [ menuItems, setMenuItems ] = useState<MenuProps['items']>([]);
const main_window_menu_items: MenuProps['items'] = [
{
key: 'setting',
label: 'Setting',
icon: <IconSetting/>,
},
{
key: 'upgrade',
label: 'Upgrade',
icon: <IconUpgrade />,
disabled: true,
},
{
key: 'help',
label: 'Help',
icon: <IconHelp />,
},
{
key: 'about',
label: 'About',
icon: <IconAbout />,
},
];
const edit_menu_items: MenuProps['items'] = [
{
key: 'import',
label: 'Import',
icon: <IconImport/>,
},
{
key: 'export',
label: 'Export',
icon: <IconExport />,
},
];
const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
console.log(`Click on item ${key}`);
}
useEffect(() => {
if (appWindow.label === 'main') {
setMenuItems(main_window_menu_items);
} else if (appWindow.label === 'edit') {
setMenuItems(edit_menu_items);
}
})
return (
<Menu onClick={handleMenuClick}>
{
menuItems?.map((item) => {
return (
<Menu.Item key={item?.key} icon={item?.icon}>
{item?.label}
</Menu.Item>
)
})
}
</Menu>
)
}
ItemType
is a union type of MenuItemType | SubMenuType | MenuItemGroupType | MenuDividerType | null
only 2 types have icon
property and not all of them have label
property
# ./node_modules/antd/es/menu/hooks/useItems.d.ts
export type ItemType = MenuItemType | SubMenuType | MenuItemGroupType | MenuDividerType | null;
So, you either
map
function (I don't know if it's possible)icon
& label
propertiesimport React, { useState, useEffect } from 'react';
import { Menu } from 'antd';
import type { ItemType, MenuItemType, SubMenuType } from "antd/es/menu/hooks/useItems";
const IconSample = () => <span>tada!</span>;
const appWindow = {
label: 'main'
};
type MyItemType = MenuItemType | SubMenuType;
const mainWindowMenuItems: MyItemType[] = [
{
key: 'setting',
label: 'Setting',
icon: <IconSample />,
},
{
key: 'upgrade',
label: 'Upgrade',
icon: <IconSample />,
disabled: true,
},
{
key: 'help',
label: 'Help',
icon: <IconSample />,
},
{
key: 'about',
label: 'About',
icon: <IconSample />,
}
];
const editMenuItems: MyItemType[] = [
{
key: 'import',
label: 'Import',
icon: <IconSample />,
},
{
key: 'export',
label: 'Export',
icon: <IconSample />,
},
];
export function CustomAppBarMenu() {
let menuItems: MyItemType[] = [];
if (appWindow.label === 'main') {
menuItems = mainWindowMenuItems;
} else if (appWindow.label === 'edit') {
menuItems = editMenuItems;
}
return (
<Menu>
{
menuItems?.map((item) => {
return (
<Menu.Item key={item?.key} icon={item?.icon}>
{item?.label}
</Menu.Item>
)
})
}
</Menu>
)
}