diff --git a/docs/demo/fragment.md b/docs/demo/fragment.md
deleted file mode 100644
index 8d04c249..00000000
--- a/docs/demo/fragment.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## fragment
-
-<code src="../examples/fragment.tsx"></code>
diff --git a/docs/examples/antd.tsx b/docs/examples/antd.tsx
index f5bd0bba..7796cd24 100644
--- a/docs/examples/antd.tsx
+++ b/docs/examples/antd.tsx
@@ -2,7 +2,9 @@
 
 import React from 'react';
 import type { CSSMotionProps } from 'rc-motion';
-import Menu, { SubMenu, Item as MenuItem, Divider, MenuProps } from '../../src';
+import Menu from 'rc-menu';
+import type { ItemType } from '@/interface';
+import type { MenuProps } from 'rc-menu';
 import '../../assets/index.less';
 
 function handleClick(info) {
@@ -48,75 +50,142 @@ const motionMap: Record<MenuProps['mode'], CSSMotionProps> = {
   vertical: verticalMotion,
 };
 
-const nestSubMenu = (
-  <SubMenu
-    title={<span className="submenu-title-wrapper">offset sub menu 2</span>}
-    key="4"
-    popupOffset={[10, 15]}
-  >
-    <MenuItem key="4-1">inner inner</MenuItem>
-    <Divider />
-    <SubMenu
-      key="4-2"
-      title={<span className="submenu-title-wrapper">sub menu 1</span>}
-    >
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub 4-2-0</span>}
-        key="4-2-0"
-      >
-        <MenuItem key="4-2-0-1">inner inner</MenuItem>
-        <MenuItem key="4-2-0-2">inner inner2</MenuItem>
-      </SubMenu>
-      <MenuItem key="4-2-1">inn</MenuItem>
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub menu 4</span>}
-        key="4-2-2"
-      >
-        <MenuItem key="4-2-2-1">inner inner</MenuItem>
-        <MenuItem key="4-2-2-2">inner inner2</MenuItem>
-      </SubMenu>
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub menu 3</span>}
-        key="4-2-3"
-      >
-        <MenuItem key="4-2-3-1">inner inner</MenuItem>
-        <MenuItem key="4-2-3-2">inner inner2</MenuItem>
-      </SubMenu>
-    </SubMenu>
-  </SubMenu>
-);
+const nestSubMenu: ItemType = {
+  key: '4',
+  type: 'submenu',
+  label: <span className="submenu-title-wrapper">offset sub menu 2</span>,
+  popupOffset: [10, 15],
+  children: [
+    {
+      key: '4-1',
+      label: 'inner inner',
+    },
+    {
+      type: 'divider',
+    },
+    {
+      key: '4-2',
+      type: 'submenu',
+      label: <span className="submenu-title-wrapper">sub menu 1</span>,
+      children: [
+        {
+          key: '4-2-0',
+          type: 'submenu',
+          label: <span className="submenu-title-wrapper">sub 4-2-0</span>,
+          children: [
+            {
+              key: '4-2-0-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-0-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+        {
+          key: '4-2-1',
+          label: 'inn',
+        },
+        {
+          key: '4-2-2',
+          type: 'submenu',
+          label: <span className="submenu-title-wrapper">sub menu 4</span>,
+          children: [
+            {
+              key: '4-2-2-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-2-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+        {
+          key: '4-2-3',
+          type: 'submenu',
+          label: <span className="submenu-title-wrapper">sub menu 3</span>,
+          children: [
+            {
+              key: '4-2-3-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-3-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
 
 function onOpenChange(value) {
   console.log('onOpenChange', value);
 }
 
-const children1 = [
-  <SubMenu
-    title={<span className="submenu-title-wrapper">sub menu</span>}
-    key="1"
-  >
-    <MenuItem key="1-1">0-1</MenuItem>
-    <MenuItem key="1-2">0-2</MenuItem>
-  </SubMenu>,
+const items1: ItemType[] = [
+  {
+    type: 'submenu',
+    key: '1',
+    label: <span className="submenu-title-wrapper">sub menu</span>,
+    children: [
+      {
+        key: '1-1',
+        label: '0-1',
+      },
+      {
+        key: '1-2',
+        label: '0-2',
+      },
+    ],
+  },
   nestSubMenu,
-  <MenuItem key="2">1</MenuItem>,
-  <MenuItem key="3">outer</MenuItem>,
-  <MenuItem key="5" disabled>
-    disabled
-  </MenuItem>,
-  <MenuItem key="6">outer3</MenuItem>,
+  {
+    key: '2',
+    label: '1',
+  },
+  {
+    key: '3',
+    label: 'outer',
+  },
+  {
+    key: '5',
+    label: 'disabled',
+    disabled: true,
+  },
+  {
+    key: '6',
+    label: 'outer3',
+  },
 ];
 
-const children2 = [
-  <SubMenu
-    title={<span className="submenu-title-wrapper">sub menu</span>}
-    key="1"
-  >
-    <MenuItem key="1-1">0-1</MenuItem>
-    <MenuItem key="1-2">0-2</MenuItem>
-  </SubMenu>,
-  <MenuItem key="2">1</MenuItem>,
-  <MenuItem key="3">outer</MenuItem>,
+const items2 = [
+  {
+    type: 'submenu',
+    key: '1',
+    label: <span className="submenu-title-wrapper">sub menu</span>,
+    children: [
+      {
+        key: '1-1',
+        label: '0-1',
+      },
+      {
+        key: '1-2',
+        label: '0-2',
+      },
+    ],
+  },
+  {
+    key: '2',
+    label: '1',
+  },
+  {
+    key: '3',
+    label: 'outer',
+  },
 ];
 
 const customizeIndicator = <span>Add More Items</span>;
@@ -127,7 +196,7 @@ interface CommonMenuProps extends MenuProps {
 }
 
 interface CommonMenuState {
-  children: React.ReactNode;
+  items: ItemType[];
   overflowedIndicator: React.ReactNode;
 }
 
@@ -136,13 +205,14 @@ export class CommonMenu extends React.Component<
   CommonMenuState
 > {
   state: CommonMenuState = {
-    children: children1,
+    items: items1 as ItemType[],
     overflowedIndicator: undefined,
   };
 
   toggleChildren = () => {
-    this.setState(({ children }) => ({
-      children: children === children1 ? children2 : children1,
+    // @ts-ignore
+    this.setState(({ items }) => ({
+      items: items === items1 ? items2 : items1,
     }));
   };
 
@@ -155,13 +225,13 @@ export class CommonMenu extends React.Component<
 
   render() {
     const { triggerSubMenuAction } = this.props;
-    const { children, overflowedIndicator } = this.state;
+    const { items, overflowedIndicator } = this.state;
     return (
       <div>
         {this.props.updateChildrenAndOverflowedIndicator && (
           <div>
             <button type="button" onClick={this.toggleChildren}>
-              toggle children
+              toggle items
             </button>
             <button type="button" onClick={this.toggleOverflowedIndicator}>
               toggle overflowedIndicator
@@ -175,9 +245,8 @@ export class CommonMenu extends React.Component<
           selectedKeys={['3']}
           overflowedIndicator={overflowedIndicator}
           {...this.props}
-        >
-          {children}
-        </Menu>
+          items={items}
+        />
       </div>
     );
   }
diff --git a/docs/examples/custom-icon.tsx b/docs/examples/custom-icon.tsx
index 7b1f075b..a9f37faf 100644
--- a/docs/examples/custom-icon.tsx
+++ b/docs/examples/custom-icon.tsx
@@ -1,7 +1,8 @@
 /* eslint-disable no-console, no-param-reassign */
 import * as React from 'react';
-import Menu, { SubMenu, Item as MenuItem, Divider } from '../../src';
+import Menu from 'rc-menu';
 import '../../assets/index.less';
+import type { ItemType } from '@/interface';
 
 const getSvgIcon = (style = {}, text?: React.ReactNode) => {
   if (text) {
@@ -67,50 +68,126 @@ class Demo extends React.Component {
     console.log(info);
   };
 
-  renderNestSubMenu = (props = {}) => (
-    <SubMenu
-      title={<span>offset sub menu 2</span>}
-      key="4"
-      popupOffset={[10, 15]}
-      {...props}
-    >
-      <MenuItem key="4-1">inner inner</MenuItem>
-      <Divider />
-      <SubMenu key="4-2" title={<span>sub menu 3</span>}>
-        <SubMenu title="sub 4-2-0" key="4-2-0">
-          <MenuItem key="4-2-0-1">inner inner</MenuItem>
-          <MenuItem key="4-2-0-2">inner inner2</MenuItem>
-        </SubMenu>
-        <MenuItem key="4-2-1">inn</MenuItem>
-        <SubMenu title={<span>sub menu 4</span>} key="4-2-2">
-          <MenuItem key="4-2-2-1">inner inner</MenuItem>
-          <MenuItem key="4-2-2-2">inner inner2</MenuItem>
-        </SubMenu>
-        <SubMenu title="sub 4-2-3" key="4-2-3">
-          <MenuItem key="4-2-3-1">inner inner</MenuItem>
-          <MenuItem key="4-2-3-2">inner inner2</MenuItem>
-        </SubMenu>
-      </SubMenu>
-    </SubMenu>
-  );
+  renderNestSubMenu = (props = {}) => ({
+    key: '4',
+    type: 'submenu',
+    label: <span>offset sub menu 2</span>,
+    popupOffset: [10, 15],
+    children: [
+      {
+        key: '4-1',
+        label: 'inner inner',
+      },
+      {
+        type: 'divider',
+      },
+      {
+        key: '4-2',
+        type: 'submenu',
+        label: <span>sub menu 3</span>,
+        children: [
+          {
+            key: '4-2-0',
+            type: 'submenu',
+            label: 'sub 4-2-0',
+            children: [
+              {
+                key: '4-2-0-1',
+                label: 'inner inner',
+              },
+              {
+                key: '4-2-0-2',
+                label: 'inner inner2',
+              },
+            ],
+          },
+          {
+            key: '4-2-1',
+            label: 'inn',
+          },
+          {
+            key: '4-2-2',
+            type: 'submenu',
+            label: <span>sub menu 4</span>,
+            children: [
+              {
+                key: '4-2-2-1',
+                label: 'inner inner',
+              },
+              {
+                key: '4-2-2-2',
+                label: 'inner inner2',
+              },
+            ],
+          },
+          {
+            key: '4-2-3',
+            type: 'submenu',
+            label: 'sub 4-2-3',
+            children: [
+              {
+                key: '4-2-3-1',
+                label: 'inner inner',
+              },
+              {
+                key: '4-2-3-2',
+                label: 'inner inner2',
+              },
+            ],
+          },
+        ],
+      },
+    ],
+    ...props,
+  });
 
-  renderCommonMenu = (props = {}) => (
-    <Menu
-      onClick={this.handleClick}
-      onOpenChange={this.onOpenChange}
-      {...props}
-    >
-      <SubMenu title={<span>sub menu</span>} key="1">
-        <MenuItem key="1-1">0-1</MenuItem>
-        <MenuItem key="1-2">0-2</MenuItem>
-      </SubMenu>
-      {this.renderNestSubMenu()}
-      <MenuItem key="2">1</MenuItem>
-      <MenuItem key="3">outer</MenuItem>
-      <MenuItem disabled>disabled</MenuItem>
-      <MenuItem key="5">outer3</MenuItem>
-    </Menu>
-  );
+  renderCommonMenu = (props = {}) => {
+    const items: ItemType[] = [
+      {
+        key: '1',
+        type: 'submenu',
+        label: <span>sub menu</span>,
+        children: [
+          {
+            key: '1-1',
+            label: '0-1',
+          },
+          {
+            key: '1-2',
+            label: '0-2',
+          },
+        ],
+      },
+      // @ts-ignore
+      this.renderNestSubMenu(),
+      {
+        key: '2',
+        label: '1',
+      },
+      {
+        key: '3',
+        label: 'outer',
+      },
+      {
+        key: '44',
+        label: 'disabled',
+        disabled: true,
+      },
+      {
+        key: '5',
+        label: 'outer3',
+      },
+    ];
+
+    return (
+      <Menu
+        onClick={this.handleClick}
+        onOpenChange={this.onOpenChange}
+        items={items}
+        {...props}
+      />
+    );
+  };
 
   render() {
     const verticalMenu = this.renderCommonMenu({
diff --git a/docs/examples/debug.tsx b/docs/examples/debug.tsx
index a9db1e87..488833a7 100644
--- a/docs/examples/debug.tsx
+++ b/docs/examples/debug.tsx
@@ -2,8 +2,8 @@
 
 import React, { useRef } from 'react';
 import type { CSSMotionProps } from 'rc-motion';
-import Menu, { ItemGroup as MenuItemGroup, MenuItem } from '../../src';
-import type { MenuProps } from '../../src';
+import Menu from 'rc-menu';
+import type { MenuProps } from 'rc-menu';
 import '../../assets/index.less';
 import '../../assets/menu.less';
 import type { MenuInfo, MenuRef } from '@/interface';
@@ -69,9 +69,7 @@ export default () => {
   return (
     <>
       <div>
-        <Menu ref={menuRef}>
-          <MenuItem key="light">Light</MenuItem>
-        </Menu>
+        <Menu ref={menuRef} items={[{ key: 'light', label: 'Light' }]} />
         <button onClick={() => menuRef.current.focus()}>focus</button>
         <select value={mode} onChange={e => setMode(e.target.value as any)}>
           <option value="inline">Inline</option>
@@ -109,7 +107,6 @@ export default () => {
 
       <div style={{ width: narrow ? 350 : undefined }}>
         <Menu
-          // direction="rtl"
           defaultOpenKeys={['sub', 'nest']}
           forceSubMenuRender={forceRender}
           mode={mode}
@@ -119,45 +116,91 @@ export default () => {
           inlineCollapsed={inlineCollapsed}
           openKeys={openKeys}
           onOpenChange={newOpenKeys => setOpenKeys(newOpenKeys)}
-        >
-          <Menu.Item key="mail">
-            <a href="http://www.taobao.com">Navigation One</a>
-          </Menu.Item>
-          <Menu.Item key="next" onClick={onClick}>
-            Next Item
-          </Menu.Item>
-          <Menu.SubMenu title="Sub Menu" key="sub" onClick={onSubMenuClick}>
-            <Menu.Item key="sub1" onClick={onClick}>
-              Sub Item 1
-            </Menu.Item>
-            <Menu.Item key="sub2">Sub Item 2</Menu.Item>
-
-            <Menu.SubMenu title="Nest Menu" key="nest">
-              <MenuItemGroup title="group 1" key="grp1">
-                <Menu.Item key="21">2</Menu.Item>
-                <Menu.Item key="22">3</Menu.Item>
-              </MenuItemGroup>
-              <MenuItemGroup title="group 2" key="grp2">
-                <Menu.Item key="31">4</Menu.Item>
-                <Menu.Item key="32">5</Menu.Item>
-              </MenuItemGroup>
-            </Menu.SubMenu>
-          </Menu.SubMenu>
-          <Menu.Item key="disabled" disabled>
-            Disabled Item
-          </Menu.Item>
-
-          <Menu.SubMenu
-            title="Disabled Sub Menu"
-            key="disabled-sub"
-            onClick={onSubMenuClick}
-            disabled
-          >
-            <Menu.Item key="dis-sub1" onClick={onClick}>
-              Disabled Sub Item 1
-            </Menu.Item>
-          </Menu.SubMenu>
-        </Menu>
+          items={[
+            {
+              key: 'mail',
+              label: <a href="http://www.taobao.com">Navigation One</a>,
+            },
+            {
+              key: 'next',
+              label: 'Next Item',
+              onClick: onClick,
+            },
+            {
+              key: 'sub',
+              label: 'Sub Menu',
+              type: 'submenu',
+              onClick: onSubMenuClick,
+              children: [
+                {
+                  key: 'sub1',
+                  label: 'Sub Item 1',
+                  onClick: onClick,
+                },
+                {
+                  key: 'sub2',
+                  label: 'Sub Item 2',
+                },
+                {
+                  key: 'nest',
+                  label: 'Nest Menu',
+                  type: 'submenu',
+                  children: [
+                    {
+                      key: 'grp1',
+                      type: 'group',
+                      label: 'group 1',
+                      children: [
+                        {
+                          key: '21',
+                          label: '2',
+                        },
+                        {
+                          key: '22',
+                          label: '3',
+                        },
+                      ],
+                    },
+                    {
+                      key: 'grp2',
+                      type: 'group',
+                      label: 'group 2',
+                      children: [
+                        {
+                          key: '31',
+                          label: '4',
+                        },
+                        {
+                          key: '32',
+                          label: '5',
+                        },
+                      ],
+                    },
+                  ],
+                },
+              ],
+            },
+            {
+              key: 'disabled',
+              label: 'Disabled Item',
+              disabled: true,
+            },
+            {
+              key: 'disabled-sub',
+              label: 'Disabled Sub Menu',
+              type: 'submenu',
+              onClick: onSubMenuClick,
+              disabled: true,
+              children: [
+                {
+                  key: 'dis-sub1',
+                  label: 'Disabled Sub Item 1',
+                  onClick: onClick,
+                },
+              ],
+            },
+          ]}
+        />
       </div>
     </>
   );
diff --git a/docs/examples/fragment.tsx b/docs/examples/fragment.tsx
deleted file mode 100644
index 8dc52457..00000000
--- a/docs/examples/fragment.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import Menu, { SubMenu, Item as MenuItem, Divider } from 'rc-menu';
-import '../../assets/index.less';
-
-export default () => (
-  <Menu style={{ width: 200 }}>
-    <SubMenu title="sub menu" key="1">
-      <MenuItem key="1-1">0-1</MenuItem>
-      <MenuItem key="1-2">0-2</MenuItem>
-    </SubMenu>
-    <MenuItem key="2">Menu Item</MenuItem>
-    <MenuItem key="3">outer</MenuItem>
-    <>
-      <SubMenu key="4" title="sub menu">
-        <MenuItem key="4-1">inner inner</MenuItem>
-        <Divider />
-        <SubMenu key="4-2" title="sub menu">
-          <MenuItem key="4-2-1">inn</MenuItem>
-          <SubMenu title="sub menu" key="4-2-2">
-            <MenuItem key="4-2-2-1">inner inner</MenuItem>
-            <MenuItem key="4-2-2-2">inner inner2</MenuItem>
-          </SubMenu>
-        </SubMenu>
-      </SubMenu>
-      <MenuItem disabled>disabled</MenuItem>
-      <MenuItem key="4-3">outer3</MenuItem>
-    </>
-  </Menu>
-);
diff --git a/docs/examples/items-ref.tsx b/docs/examples/items-ref.tsx
index dc18f9f1..ff0121b2 100644
--- a/docs/examples/items-ref.tsx
+++ b/docs/examples/items-ref.tsx
@@ -2,7 +2,7 @@
 
 import React, { useRef } from 'react';
 import '../../assets/index.less';
-import Menu from '../../src';
+import Menu from 'rc-menu';
 
 export default () => {
   const ref1 = useRef();
diff --git a/docs/examples/items.tsx b/docs/examples/items.tsx
index a0044731..e5a05467 100644
--- a/docs/examples/items.tsx
+++ b/docs/examples/items.tsx
@@ -1,7 +1,7 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu from '../../src';
+import Menu from 'rc-menu';
 import '../../assets/index.less';
 
 export default () => (
diff --git a/docs/examples/keyPath.tsx b/docs/examples/keyPath.tsx
index 30a5542e..c2892c4c 100644
--- a/docs/examples/keyPath.tsx
+++ b/docs/examples/keyPath.tsx
@@ -1,7 +1,7 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
@@ -12,21 +12,61 @@ class Test extends React.Component {
 
   getMenu() {
     return (
-      <Menu onClick={this.onClick} mode="inline">
-        <SubMenu key="1" title="submenu1">
-          <MenuItem key="1-1">item1-1</MenuItem>
-          <MenuItem key="1-2">item1-2</MenuItem>
-        </SubMenu>
-        <SubMenu key="2" title="submenu2">
-          <MenuItem key="2-1">item2-1</MenuItem>
-          <MenuItem key="2-2">item2-2</MenuItem>
-          <SubMenu key="2-3" title="submenu2-3">
-            <MenuItem key="2-3-1">item2-3-1</MenuItem>
-            <MenuItem key="2-3-2">item2-3-2</MenuItem>
-          </SubMenu>
-        </SubMenu>
-        <MenuItem key="3">item3</MenuItem>
-      </Menu>
+      <Menu
+        onClick={this.onClick}
+        mode="inline"
+        items={[
+          {
+            key: '1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: '1-1',
+                label: 'item1-1',
+              },
+              {
+                key: '1-2',
+                label: 'item1-2',
+              },
+            ],
+          },
+          {
+            key: '2',
+            label: 'submenu2',
+            type: 'submenu',
+            children: [
+              {
+                key: '2-1',
+                label: 'item2-1',
+              },
+              {
+                key: '2-2',
+                label: 'item2-2',
+              },
+              {
+                key: '2-3',
+                label: 'submenu2-3',
+                type: 'submenu',
+                children: [
+                  {
+                    key: '2-3-1',
+                    label: 'item2-3-1',
+                  },
+                  {
+                    key: '2-3-2',
+                    label: 'item2-3-2',
+                  },
+                ],
+              },
+            ],
+          },
+          {
+            key: '3',
+            label: 'item3',
+          },
+        ]}
+      />
     );
   }
 
diff --git a/docs/examples/menuItemGroup.tsx b/docs/examples/menuItemGroup.tsx
index b598ddda..61c9abd4 100644
--- a/docs/examples/menuItemGroup.tsx
+++ b/docs/examples/menuItemGroup.tsx
@@ -1,22 +1,48 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { Item as MenuItem, ItemGroup as MenuItemGroup } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
 export default () => (
   <div>
     <h2>menu item group</h2>
-    <Menu style={{ margin: 20, width: 300 }} onClick={() => console.log('click')}>
-      <MenuItemGroup title="group 1" key="2">
-        <MenuItem key="21">2</MenuItem>
-        <MenuItem key="22">3</MenuItem>
-      </MenuItemGroup>
-      <MenuItemGroup title="group 2" key="3">
-        <MenuItem key="31">4</MenuItem>
-        <MenuItem key="32">5</MenuItem>
-      </MenuItemGroup>
-    </Menu>
+    <Menu
+      style={{ margin: 20, width: 300 }}
+      onClick={() => console.log('click')}
+      items={[
+        {
+          type: 'group',
+          label: 'group 1',
+          key: '2',
+          children: [
+            {
+              key: '21',
+              label: '2',
+            },
+            {
+              key: '22',
+              label: '3',
+            },
+          ],
+        },
+        {
+          type: 'group',
+          label: 'group 2',
+          key: '3',
+          children: [
+            {
+              key: '31',
+              label: '4',
+            },
+            {
+              key: '32',
+              label: '5',
+            },
+          ],
+        },
+      ]}
+    />
   </div>
 );
diff --git a/docs/examples/multiple.tsx b/docs/examples/multiple.tsx
index 9b9f5057..60572ce2 100644
--- a/docs/examples/multiple.tsx
+++ b/docs/examples/multiple.tsx
@@ -1,7 +1,7 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { SubMenu, Item as MenuItem, Divider } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
@@ -27,31 +27,82 @@ function Demo() {
       onSelect={handleSelect}
       onDeselect={handleDeselect}
       defaultSelectedKeys={['2', '1-1']}
-    >
-      <SubMenu title={titleRight} key="1">
-        <MenuItem key="1-1">0-1</MenuItem>
-        <MenuItem key="1-2">0-2</MenuItem>
-      </SubMenu>
-      <MenuItem key="2" disabled>
-        can not deselect me, i am disabled
-      </MenuItem>
-      <MenuItem key="3">outer</MenuItem>
-      <SubMenu title={titleRight1} key="4">
-        <MenuItem key="4-1">inner inner</MenuItem>
-        <Divider />
-        <SubMenu key="4-2" title={titleRight2}>
-          <MenuItem key="4-2-1">inn</MenuItem>
-          <SubMenu title={titleRight3} key="4-2-2">
-            <MenuItem key="4-2-2-1">inner inner</MenuItem>
-            <MenuItem key="4-2-2-2">inner inner2</MenuItem>
-          </SubMenu>
-        </SubMenu>
-      </SubMenu>
-      <MenuItem disabled key="disabled">
-        disabled
-      </MenuItem>
-      <MenuItem key="4-3">outer3</MenuItem>
-    </Menu>
+      items={[
+        {
+          label: titleRight,
+          type: 'submenu',
+          key: '1',
+          children: [
+            {
+              label: '0-1',
+              key: '1-1',
+            },
+            {
+              label: '0-2',
+              key: '1-2',
+            },
+          ],
+        },
+        {
+          label: 'can not deselect me, i am disabled',
+          key: '2',
+          disabled: true,
+        },
+        {
+          label: 'outer',
+          key: '3',
+        },
+        {
+          label: titleRight1,
+          type: 'submenu',
+          key: '4',
+          children: [
+            {
+              label: 'inner inner',
+              key: '4-1',
+            },
+            {
+              type: 'divider',
+            },
+            {
+              label: titleRight2,
+              type: 'submenu',
+              key: '4-2',
+              children: [
+                {
+                  label: 'inn',
+                  key: '4-2-1',
+                },
+                {
+                  label: titleRight3,
+                  type: 'submenu',
+                  key: '4-2-2',
+                  children: [
+                    {
+                      label: 'inner inner',
+                      key: '4-2-2-1',
+                    },
+                    {
+                      label: 'inner inner2',
+                      key: '4-2-2-2',
+                    },
+                  ],
+                },
+              ],
+            },
+          ],
+        },
+        {
+          label: 'disabled',
+          key: 'disabled',
+          disabled: true,
+        },
+        {
+          label: 'outer3',
+          key: '4-3',
+        },
+      ]}
+    />
   );
   return (
     <div>
diff --git a/docs/examples/openKeys.tsx b/docs/examples/openKeys.tsx
index f83ec15d..ee37d07e 100644
--- a/docs/examples/openKeys.tsx
+++ b/docs/examples/openKeys.tsx
@@ -1,7 +1,7 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
@@ -28,17 +28,43 @@ class Test extends React.Component {
         mode="inline"
         onOpenChange={this.onOpenChange}
         openKeys={this.state.openKeys}
-      >
-        <SubMenu key="1" title="submenu1">
-          <MenuItem key="1-1">item1-1</MenuItem>
-          <MenuItem key="1-2">item1-2</MenuItem>
-        </SubMenu>
-        <SubMenu key="2" title="submenu2">
-          <MenuItem key="2-1">item2-1</MenuItem>
-          <MenuItem key="2-2">item2-2</MenuItem>
-        </SubMenu>
-        <MenuItem key="3">item3</MenuItem>
-      </Menu>
+        items={[
+          {
+            key: '1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: '1-1',
+                label: 'item1-1',
+              },
+              {
+                key: '1-2',
+                label: 'item1-2',
+              },
+            ],
+          },
+          {
+            key: '2',
+            label: 'submenu2',
+            type: 'submenu',
+            children: [
+              {
+                key: '2-1',
+                label: 'item2-1',
+              },
+              {
+                key: '2-2',
+                label: 'item2-2',
+              },
+            ],
+          },
+          {
+            key: '3',
+            label: 'item3',
+          },
+        ]}
+      />
     );
   }
 
diff --git a/docs/examples/rtl-antd.tsx b/docs/examples/rtl-antd.tsx
index 91984cf7..c85e12ef 100644
--- a/docs/examples/rtl-antd.tsx
+++ b/docs/examples/rtl-antd.tsx
@@ -2,8 +2,9 @@
 
 import React from 'react';
 import type { CSSMotionProps } from 'rc-motion';
-import Menu, { SubMenu, Item as MenuItem, Divider, MenuProps } from 'rc-menu';
+import Menu, { type MenuProps } from 'rc-menu';
 import '../../assets/index.less';
+import type { ItemType } from '@/interface';
 
 function handleClick(info) {
   console.log(`clicked ${info.key}`);
@@ -48,93 +49,161 @@ const motionMap: Record<MenuProps['mode'], CSSMotionProps> = {
   vertical: verticalMotion,
 };
 
-const nestSubMenu = (
-  <SubMenu
-    title={<span className="submenu-title-wrapper">offset sub menu 2</span>}
-    key="4"
-    popupOffset={[-10, 15]}
-  >
-    <MenuItem key="4-1">inner inner</MenuItem>
-    <Divider />
-    <SubMenu
-      key="4-2"
-      title={<span className="submenu-title-wrapper">sub menu 1</span>}
-    >
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub 4-2-0</span>}
-        key="4-2-0"
-      >
-        <MenuItem key="4-2-0-1">inner inner</MenuItem>
-        <MenuItem key="4-2-0-2">inner inner2</MenuItem>
-      </SubMenu>
-      <MenuItem key="4-2-1">inn</MenuItem>
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub menu 4</span>}
-        key="4-2-2"
-      >
-        <MenuItem key="4-2-2-1">inner inner</MenuItem>
-        <MenuItem key="4-2-2-2">inner inner2</MenuItem>
-      </SubMenu>
-      <SubMenu
-        title={<span className="submenu-title-wrapper">sub menu 3</span>}
-        key="4-2-3"
-      >
-        <MenuItem key="4-2-3-1">inner inner</MenuItem>
-        <MenuItem key="4-2-3-2">inner inner2</MenuItem>
-      </SubMenu>
-    </SubMenu>
-  </SubMenu>
-);
+const nestSubMenu = {
+  key: '4',
+  label: <span className="submenu-title-wrapper">offset sub menu 2</span>,
+  type: 'submenu',
+  popupOffset: [-10, 15],
+  children: [
+    {
+      key: '4-1',
+      label: 'inner inner',
+    },
+    {
+      type: 'divider',
+    },
+    {
+      key: '4-2',
+      label: <span className="submenu-title-wrapper">sub menu 1</span>,
+      type: 'submenu',
+      children: [
+        {
+          key: '4-2-0',
+          label: <span className="submenu-title-wrapper">sub 4-2-0</span>,
+          type: 'submenu',
+          children: [
+            {
+              key: '4-2-0-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-0-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+        {
+          key: '4-2-1',
+          label: 'inn',
+        },
+        {
+          key: '4-2-2',
+          label: <span className="submenu-title-wrapper">sub menu 4</span>,
+          type: 'submenu',
+          children: [
+            {
+              key: '4-2-2-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-2-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+        {
+          key: '4-2-3',
+          label: <span className="submenu-title-wrapper">sub menu 3</span>,
+          type: 'submenu',
+          children: [
+            {
+              key: '4-2-3-1',
+              label: 'inner inner',
+            },
+            {
+              key: '4-2-3-2',
+              label: 'inner inner2',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
 
 function onOpenChange(value) {
   console.log('onOpenChange', value);
 }
 
-const children1 = [
-  <SubMenu
-    title={<span className="submenu-title-wrapper">sub menu</span>}
-    key="1"
-  >
-    <MenuItem key="1-1">0-1</MenuItem>
-    <MenuItem key="1-2">0-2</MenuItem>
-  </SubMenu>,
+const items1 = [
+  {
+    key: '1',
+    label: <span className="submenu-title-wrapper">sub menu</span>,
+    type: 'submenu',
+    children: [
+      {
+        key: '1-1',
+        label: '0-1',
+      },
+      {
+        key: '1-2',
+        label: '0-2',
+      },
+    ],
+  },
   nestSubMenu,
-  <MenuItem key="2">1</MenuItem>,
-  <MenuItem key="3">outer</MenuItem>,
-  <MenuItem key="5" disabled>
-    disabled
-  </MenuItem>,
-  <MenuItem key="6">outer3</MenuItem>,
+  {
+    key: '2',
+    label: '1',
+  },
+  {
+    key: '3',
+    label: 'outer',
+  },
+  {
+    key: '5',
+    label: 'disabled',
+    disabled: true,
+  },
+  {
+    key: '6',
+    label: 'outer3',
+  },
 ];
 
-const children2 = [
-  <SubMenu
-    title={<span className="submenu-title-wrapper">sub menu</span>}
-    key="1"
-  >
-    <MenuItem key="1-1">0-1</MenuItem>
-    <MenuItem key="1-2">0-2</MenuItem>
-  </SubMenu>,
-  <MenuItem key="2">1</MenuItem>,
-  <MenuItem key="3">outer</MenuItem>,
+const items2 = [
+  {
+    key: '1',
+    label: <span className="submenu-title-wrapper">sub menu</span>,
+    type: 'submenu',
+    children: [
+      {
+        key: '1-1',
+        label: '0-1',
+      },
+      {
+        key: '1-2',
+        label: '0-2',
+      },
+    ],
+  },
+  {
+    key: '2',
+    label: '1',
+  },
+  {
+    key: '3',
+    label: 'outer',
+  },
 ];
 
 const customizeIndicator = <span>Add More Items</span>;
 
 interface CommonMenuState {
-    children: React.ReactNode;
-    overflowedIndicator?: React.ReactNode;
+  items: ItemType[];
+  overflowedIndicator?: React.ReactNode;
 }
 
 class CommonMenu extends React.Component<any, CommonMenuState> {
   state = {
-    children: children1,
+    items: items1,
     overflowedIndicator: undefined,
   } as CommonMenuState;
 
-  toggleChildren = () => {
-    this.setState(({ children }) => ({
-      children: children === children1 ? children2 : children1,
+  toggleItems = () => {
+    // @ts-ignore
+    this.setState(({ items }) => ({
+      items: items === items1 ? items2 : items1,
     }));
   };
 
@@ -147,13 +216,13 @@ class CommonMenu extends React.Component<any, CommonMenuState> {
 
   render() {
     const { updateChildrenAndOverflowedIndicator, ...restProps } = this.props;
-    const { children, overflowedIndicator } = this.state;
+    const { items, overflowedIndicator } = this.state;
     return (
       <div>
         {updateChildrenAndOverflowedIndicator && (
           <div>
-            <button type="button" onClick={this.toggleChildren}>
-              toggle children
+            <button type="button" onClick={this.toggleItems}>
+              toggle items
             </button>
             <button type="button" onClick={this.toggleOverflowedIndicator}>
               toggle overflowedIndicator
@@ -167,9 +236,8 @@ class CommonMenu extends React.Component<any, CommonMenuState> {
           overflowedIndicator={overflowedIndicator}
           direction="rtl"
           {...restProps}
-        >
-          {children}
-        </Menu>
+          items={items}
+        />
       </div>
     );
   }
diff --git a/docs/examples/scrollable.tsx b/docs/examples/scrollable.tsx
index a7ee7b67..4d1449d9 100644
--- a/docs/examples/scrollable.tsx
+++ b/docs/examples/scrollable.tsx
@@ -1,13 +1,16 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { Item as MenuItem } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
-const children = [];
+const items = [];
 for (let i = 0; i < 20; i += 1) {
-  children.push(<MenuItem key={String(i)}>{i}</MenuItem>);
+  items.push({
+    label: i,
+    key: String(i),
+  });
 }
 
 const menuStyle = {
@@ -19,6 +22,6 @@ const menuStyle = {
 export default () => (
   <div>
     <h2>keyboard scrollable menu</h2>
-    <Menu style={menuStyle}>{children}</Menu>
+    <Menu style={menuStyle} items={items} />
   </div>
 );
diff --git a/docs/examples/selectedKeys.tsx b/docs/examples/selectedKeys.tsx
index aa68aa97..db1bc1a5 100644
--- a/docs/examples/selectedKeys.tsx
+++ b/docs/examples/selectedKeys.tsx
@@ -1,15 +1,15 @@
 /* eslint no-console:0 */
 
 import React from 'react';
-import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
+import Menu from 'rc-menu';
 
 import '../../assets/index.less';
 
 interface TestState {
-    destroyed: boolean;
-    selectedKeys: string[];
-    openKeys: string[];
-  }
+  destroyed: boolean;
+  selectedKeys: string[];
+  openKeys: string[];
+}
 
 class Test extends React.Component<any, TestState> {
   state = {
@@ -86,17 +86,43 @@ class Test extends React.Component<any, TestState> {
         onOpenChange={this.onOpenChange}
         openKeys={this.state.openKeys}
         selectedKeys={this.state.selectedKeys}
-      >
-        <SubMenu key="1" title="submenu1">
-          <MenuItem key="1-1">item1-1</MenuItem>
-          <MenuItem key="1-2">item1-2</MenuItem>
-        </SubMenu>
-        <SubMenu key="2" title="submenu2">
-          <MenuItem key="2-1">item2-1</MenuItem>
-          <MenuItem key="2-2">item2-2</MenuItem>
-        </SubMenu>
-        <MenuItem key="3">item3</MenuItem>
-      </Menu>
+        items={[
+          {
+            key: '1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: '1-1',
+                label: 'item1-1',
+              },
+              {
+                key: '1-2',
+                label: 'item1-2',
+              },
+            ],
+          },
+          {
+            key: '2',
+            label: 'submenu2',
+            type: 'submenu',
+            children: [
+              {
+                key: '2-1',
+                label: 'item2-1',
+              },
+              {
+                key: '2-2',
+                label: 'item2-2',
+              },
+            ],
+          },
+          {
+            key: '3',
+            label: 'item3',
+          },
+        ]}
+      />
     );
   }
 
diff --git a/src/Menu.tsx b/src/Menu.tsx
index edad0c5b..d3ece685 100644
--- a/src/Menu.tsx
+++ b/src/Menu.tsx
@@ -62,9 +62,6 @@ export interface MenuProps
   rootClassName?: string;
   items?: ItemType[];
 
-  /** @deprecated Please use `items` instead */
-  children?: React.ReactNode;
-
   disabled?: boolean;
   /** @private Disable auto overflow. Pls note the prop name may refactor since we do not final decided. */
   disabledOverflow?: boolean;
@@ -173,7 +170,6 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
     className,
     tabIndex = 0,
     items,
-    children,
     direction,
 
     id,
@@ -248,10 +244,10 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
     measureChildList: React.ReactElement[],
   ] = React.useMemo(
     () => [
-      parseItems(children, items, EMPTY_LIST, _internalComponents, prefixCls),
-      parseItems(children, items, EMPTY_LIST, {}, prefixCls),
+      parseItems(items, EMPTY_LIST, _internalComponents, prefixCls),
+      parseItems(items, EMPTY_LIST, {}, prefixCls),
     ],
-    [children, items, _internalComponents],
+    [items, _internalComponents],
   );
 
   const [mounted, setMounted] = React.useState(false);
diff --git a/src/MenuItem.tsx b/src/MenuItem.tsx
index fb83fece..47671dfe 100644
--- a/src/MenuItem.tsx
+++ b/src/MenuItem.tsx
@@ -28,9 +28,6 @@ export interface MenuItemProps
 
   /** @private Do not use. Private warning empty usage */
   warnKey?: boolean;
-
-  /** @deprecated No place to use this. Should remove */
-  attribute?: Record<string, string>;
 }
 
 // Since Menu event provide the `info.item` which point to the MenuItem node instance.
diff --git a/src/interface.ts b/src/interface.ts
index f47873d1..9174e48e 100644
--- a/src/interface.ts
+++ b/src/interface.ts
@@ -53,6 +53,10 @@ export interface MenuItemType extends ItemSharedProps {
 
   key: React.Key;
 
+  title?: string;
+
+  role?: React.AriaRole;
+
   // >>>>> Active
   onMouseEnter?: MenuHoverEventHandler;
   onMouseLeave?: MenuHoverEventHandler;
@@ -62,6 +66,8 @@ export interface MenuItemType extends ItemSharedProps {
 }
 
 export interface MenuItemGroupType extends ItemSharedProps {
+  key?: React.Key;
+
   type: 'group';
 
   label?: React.ReactNode;
@@ -139,4 +145,6 @@ export type MenuRef = {
 // ======================== Component ========================
 export type ComponentType = 'submenu' | 'item' | 'group' | 'divider';
 
-export type Components = Partial<Record<ComponentType, React.ComponentType<any>>>;
+export type Components = Partial<
+  Record<ComponentType, React.ComponentType<any>>
+>;
diff --git a/src/utils/nodeUtil.tsx b/src/utils/nodeUtil.tsx
index c0b81106..bf8fec05 100644
--- a/src/utils/nodeUtil.tsx
+++ b/src/utils/nodeUtil.tsx
@@ -64,13 +64,12 @@ function convertItemsToNodes(
 }
 
 export function parseItems(
-  children: React.ReactNode | undefined,
   items: ItemType[] | undefined,
   keyPath: string[],
   components: Components,
   prefixCls?: string,
 ) {
-  let childNodes = children;
+  let childNodes;
 
   const mergedComponents: Required<Components> = {
     divider: Divider,
diff --git a/tests/Collapsed.spec.tsx b/tests/Collapsed.spec.tsx
index ee6f1c7d..e6d6c158 100644
--- a/tests/Collapsed.spec.tsx
+++ b/tests/Collapsed.spec.tsx
@@ -1,7 +1,7 @@
 /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence */
 import { act, fireEvent, render } from '@testing-library/react';
 import React from 'react';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 
 describe('Menu.Collapsed', () => {
   describe('inlineCollapse and siderCollapsed', () => {
@@ -15,13 +15,31 @@ describe('Menu.Collapsed', () => {
 
     it('should always follow openKeys when mode is switched', () => {
       const genMenu = (props?) => (
-        <Menu openKeys={['1']} mode="inline" {...props}>
-          <SubMenu key="1" title="submenu1">
-            <MenuItem key="submenu1">Option 1</MenuItem>
-            <MenuItem key="submenu2">Option 2</MenuItem>
-          </SubMenu>
-          <MenuItem key="2">menu2</MenuItem>
-        </Menu>
+        <Menu
+          openKeys={['1']}
+          mode="inline"
+          {...props}
+          items={[
+            {
+              key: '1',
+              label: 'submenu1',
+              children: [
+                {
+                  key: 'submenu1',
+                  label: 'Option 1',
+                },
+                {
+                  key: 'submenu2',
+                  label: 'Option 2',
+                },
+              ],
+            },
+            {
+              key: '2',
+              label: 'menu2',
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
@@ -49,13 +67,28 @@ describe('Menu.Collapsed', () => {
 
     it('should always follow submenu popup hidden when mode is switched', () => {
       const genMenu = (props?) => (
-        <Menu mode="vertical" {...props}>
-          <SubMenu key="1" title="submenu1">
-            <SubMenu key="1-1" title="submenu1-1">
-              <MenuItem key="Option-1">Option 1</MenuItem>
-            </SubMenu>
-          </SubMenu>
-        </Menu>
+        <Menu
+          mode="vertical"
+          {...props}
+          items={[
+            {
+              key: '1',
+              label: 'submenu1',
+              children: [
+                {
+                  key: '1-1',
+                  label: 'submenu1-1',
+                  children: [
+                    {
+                      key: 'Option-1',
+                      label: 'Option 1',
+                    },
+                  ],
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
@@ -102,15 +135,31 @@ describe('Menu.Collapsed', () => {
 
     it('should always follow openKeys when inlineCollapsed is switched', () => {
       const genMenu = (props?) => (
-        <Menu defaultOpenKeys={['1']} mode="inline" {...props}>
-          <MenuItem key="menu1">
-            <span>Option</span>
-          </MenuItem>
-          <SubMenu key="1" title="submenu1">
-            <MenuItem key="submenu1">Option</MenuItem>
-            <MenuItem key="submenu2">Option</MenuItem>
-          </SubMenu>
-        </Menu>
+        <Menu
+          defaultOpenKeys={['1']}
+          mode="inline"
+          {...props}
+          items={[
+            {
+              key: 'menu1',
+              label: <span>Option</span>,
+            },
+            {
+              key: '1',
+              label: 'submenu1',
+              children: [
+                {
+                  key: 'submenu1',
+                  label: 'Option',
+                },
+                {
+                  key: 'submenu2',
+                  label: 'Option',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
@@ -155,15 +204,31 @@ describe('Menu.Collapsed', () => {
 
     it('inlineCollapsed should works well when specify a not existed default openKeys', () => {
       const genMenu = (props?) => (
-        <Menu defaultOpenKeys={['not-existed']} mode="inline" {...props}>
-          <MenuItem key="menu1">
-            <span>Option</span>
-          </MenuItem>
-          <SubMenu key="1" title="submenu1">
-            <MenuItem key="submenu1">Option</MenuItem>
-            <MenuItem key="submenu2">Option</MenuItem>
-          </SubMenu>
-        </Menu>
+        <Menu
+          defaultOpenKeys={['not-existed']}
+          mode="inline"
+          {...props}
+          items={[
+            {
+              key: 'menu1',
+              label: <span>Option</span>,
+            },
+            {
+              key: '1',
+              label: 'submenu1',
+              children: [
+                {
+                  key: 'submenu1',
+                  label: 'Option',
+                },
+                {
+                  key: 'submenu2',
+                  label: 'Option',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
@@ -176,9 +241,6 @@ describe('Menu.Collapsed', () => {
         jest.runAllTimers();
       });
 
-      //   wrapper
-      //     .find('Overflow')
-      //     .simulate('transitionEnd', { propertyName: 'width' });
       fireEvent.transitionEnd(container.querySelector('.rc-menu-root'), {
         propertyName: 'width',
       });
@@ -189,7 +251,6 @@ describe('Menu.Collapsed', () => {
       });
 
       // Hover to show
-      //   wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter');
       fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title'));
 
       act(() => {
@@ -222,24 +283,38 @@ describe('Menu.Collapsed', () => {
           mode="inline"
           inlineCollapsed
           getPopupContainer={node => node.parentNode as HTMLElement}
-        >
-          <MenuItem key="menu1">item</MenuItem>
-          <MenuItem key="menu2" title="title">
-            item
-          </MenuItem>
-          <MenuItem key="menu3" title={undefined}>
-            item
-          </MenuItem>
-          <MenuItem key="menu4" title={null}>
-            item
-          </MenuItem>
-          <MenuItem key="menu5" title="">
-            item
-          </MenuItem>
-          <MenuItem key="menu6" title={false as unknown as string}>
-            item
-          </MenuItem>
-        </Menu>,
+          items={[
+            {
+              key: 'menu1',
+              label: 'item',
+            },
+            {
+              key: 'menu2',
+              label: 'item',
+              title: 'title',
+            },
+            {
+              key: 'menu3',
+              label: 'item',
+              title: undefined,
+            },
+            {
+              key: 'menu4',
+              label: 'item',
+              title: null,
+            },
+            {
+              key: 'menu5',
+              label: 'item',
+              title: '',
+            },
+            {
+              key: 'menu6',
+              label: 'item',
+              title: false as unknown as string,
+            },
+          ]}
+        />,
       );
 
       expect(
@@ -259,13 +334,27 @@ describe('Menu.Collapsed', () => {
           defaultSelectedKeys={['1']}
           openKeys={['3']}
           {...props}
-        >
-          <MenuItem key="1">Option 1</MenuItem>
-          <MenuItem key="2">Option 2</MenuItem>
-          <SubMenu key="3" title="Option 3">
-            <MenuItem key="4">Option 4</MenuItem>
-          </SubMenu>
-        </Menu>
+          items={[
+            {
+              key: '1',
+              label: 'Option 1',
+            },
+            {
+              key: '2',
+              label: 'Option 2',
+            },
+            {
+              key: '3',
+              label: 'Option 3',
+              children: [
+                {
+                  key: '4',
+                  label: 'Option 4',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
@@ -305,13 +394,27 @@ describe('Menu.Collapsed', () => {
           defaultSelectedKeys={['1']}
           openKeys={['3']}
           {...props}
-        >
-          <MenuItem key="1">Option 1</MenuItem>
-          <MenuItem key="2">Option 2</MenuItem>
-          <SubMenu key="3" title="Option 3">
-            <MenuItem key="4">Option 4</MenuItem>
-          </SubMenu>
-        </Menu>
+          items={[
+            {
+              key: '1',
+              label: 'Option 1',
+            },
+            {
+              key: '2',
+              label: 'Option 2',
+            },
+            {
+              key: '3',
+              label: 'Option 3',
+              children: [
+                {
+                  key: '4',
+                  label: 'Option 4',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { container, rerender } = render(genMenu());
diff --git a/tests/Focus.spec.tsx b/tests/Focus.spec.tsx
index 5457895f..9de3a60d 100644
--- a/tests/Focus.spec.tsx
+++ b/tests/Focus.spec.tsx
@@ -2,8 +2,9 @@
 import { act, fireEvent, render } from '@testing-library/react';
 import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
 import React from 'react';
-import Menu, { MenuItem, MenuItemGroup, MenuRef, SubMenu } from '../src';
+import Menu, { MenuRef } from '../src';
 
+// TODO: use userEvent instead of fireEvent for better focus testing
 describe('Focus', () => {
   beforeAll(() => {
     // Mock to force make menu item visible
@@ -29,11 +30,23 @@ describe('Focus', () => {
   it('Get focus', async () => {
     const { container } = await act(async () =>
       render(
-        <Menu mode="inline" openKeys={['s']}>
-          <SubMenu key="s" title="submenu">
-            <MenuItem key="1">1</MenuItem>
-          </SubMenu>
-        </Menu>,
+        <Menu
+          mode="inline"
+          openKeys={['s']}
+          items={[
+            {
+              key: 's',
+              type: 'submenu',
+              label: 'submenu',
+              children: [
+                {
+                  key: '1',
+                  label: '1',
+                },
+              ],
+            },
+          ]}
+        />,
       ),
     );
 
@@ -52,14 +65,29 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId } = await act(async () =>
       render(
-        <Menu ref={menuRef}>
-          <SubMenu key="bamboo" title="Disabled" disabled>
-            <MenuItem key="bamboo-child">Disabled child</MenuItem>
-          </SubMenu>
-          <MenuItem key="light" data-testid="first-focusable">
-            Light
-          </MenuItem>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              label: 'Disabled',
+              disabled: true,
+              children: [
+                {
+                  key: 'bamboo-child',
+                  label: 'Disabled child',
+                },
+              ],
+            },
+            {
+              key: 'light',
+              label: 'Light',
+              // @ts-ignore
+              'data-testid': 'first-focusable',
+            },
+          ]}
+        />,
       ),
     );
 
@@ -74,12 +102,22 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId } = await act(async () =>
       render(
-        <Menu ref={menuRef} activeKey="cat">
-          <MenuItem key="light">Light</MenuItem>
-          <MenuItem key="cat" data-testid="active-key">
-            Cat
-          </MenuItem>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          activeKey="cat"
+          items={[
+            {
+              key: 'light',
+              label: 'Light',
+            },
+            {
+              key: 'cat',
+              label: 'Cat',
+              // @ts-ignore
+              'data-testid': 'active-key',
+            },
+          ]}
+        />,
       ),
     );
     act(() => menuRef.current.focus());
@@ -93,15 +131,34 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId } = await act(async () =>
       render(
-        <Menu ref={menuRef}>
-          <MenuItemGroup title="group" key="group" />
-          <SubMenu key="bamboo" title="Disabled" disabled>
-            <MenuItem key="bamboo-child">Disabled child</MenuItem>
-          </SubMenu>
-          <MenuItem key="light" data-testid="first-focusable">
-            Light
-          </MenuItem>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          items={[
+            {
+              key: 'group',
+              type: 'group',
+              label: 'group',
+            },
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              label: 'Disabled',
+              disabled: true,
+              children: [
+                {
+                  key: 'bamboo-child',
+                  label: 'Disabled child',
+                },
+              ],
+            },
+            {
+              key: 'light',
+              label: 'Light',
+              // @ts-ignore
+              'data-testid': 'first-focusable',
+            },
+          ]}
+        />,
       ),
     );
 
@@ -116,17 +173,33 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId } = await act(async () =>
       render(
-        <Menu ref={menuRef}>
-          <MenuItemGroup title="group" key="group">
-            <MenuItem key="group-child-1" disabled>
-              group-child-1
-            </MenuItem>
-            <MenuItem key="group-child-2" data-testid="first-focusable">
-              group-child-2
-            </MenuItem>
-          </MenuItemGroup>
-          <MenuItem key="light">Light</MenuItem>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          items={[
+            {
+              key: 'group',
+              type: 'group',
+              label: 'group',
+              children: [
+                {
+                  key: 'group-child-1',
+                  label: 'group-child-1',
+                  disabled: true,
+                },
+                {
+                  key: 'group-child-2',
+                  label: 'group-child-2',
+                  // @ts-ignore
+                  'data-testid': 'first-focusable',
+                },
+              ],
+            },
+            {
+              key: 'light',
+              label: 'Light',
+            },
+          ]}
+        />,
       ),
     );
 
@@ -141,25 +214,45 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId } = await act(async () =>
       render(
-        <Menu ref={menuRef}>
-          <MenuItemGroup title="group" key="group">
-            <MenuItem key="group-child-1" disabled>
-              group-child-1
-            </MenuItem>
-            <MenuItemGroup title="nested group" key="nested-group">
-              <MenuItem key="nested-group-child-1" disabled>
-                nested-group-child-1
-              </MenuItem>
-              <MenuItem
-                key="nested-group-child-2"
-                data-testid="first-focusable"
-              >
-                nested-group-child-2
-              </MenuItem>
-            </MenuItemGroup>
-            <MenuItem key="group-child-3">group-child-3</MenuItem>
-          </MenuItemGroup>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          items={[
+            {
+              key: 'group',
+              type: 'group',
+              label: 'group',
+              children: [
+                {
+                  key: 'group-child-1',
+                  label: 'group-child-1',
+                  disabled: true,
+                },
+                {
+                  key: 'nested-group',
+                  type: 'group',
+                  label: 'nested group',
+                  children: [
+                    {
+                      key: 'nested-group-child-1',
+                      label: 'nested-group-child-1',
+                      disabled: true,
+                    },
+                    {
+                      key: 'nested-group-child-2',
+                      label: 'nested-group-child-2',
+                      // @ts-ignore
+                      'data-testid': 'first-focusable',
+                    },
+                  ],
+                },
+                {
+                  key: 'group-child-3',
+                  label: 'group-child-3',
+                },
+              ],
+            },
+          ]}
+        />,
       ),
     );
 
@@ -174,15 +267,40 @@ describe('Focus', () => {
     const menuRef = React.createRef<MenuRef>();
     const { getByTestId, getByTitle } = await act(async () =>
       render(
-        <Menu ref={menuRef}>
-          <SubMenu key="sub-menu-disabled" title="Disabled" disabled>
-            <MenuItem key="sub-menu-disabled-child">Disabled child</MenuItem>
-          </SubMenu>
-          <SubMenu key="sub-menu" data-testid="sub-menu" title="Submenu">
-            <MenuItem key="sub-menu-child-1">Submenu child</MenuItem>
-          </SubMenu>
-          <MenuItem key="light">Light</MenuItem>
-        </Menu>,
+        <Menu
+          ref={menuRef}
+          items={[
+            {
+              key: 'sub-menu-disabled',
+              type: 'submenu',
+              label: 'Disabled',
+              disabled: true,
+              children: [
+                {
+                  key: 'sub-menu-disabled-child',
+                  label: 'Disabled child',
+                },
+              ],
+            },
+            {
+              key: 'sub-menu',
+              type: 'submenu',
+              label: 'Submenu',
+              // @ts-ignore
+              'data-testid': 'sub-menu',
+              children: [
+                {
+                  key: 'sub-menu-child-1',
+                  label: 'Submenu child',
+                },
+              ],
+            },
+            {
+              key: 'light',
+              label: 'Light',
+            },
+          ]}
+        />,
       ),
     );
 
diff --git a/tests/Keyboard.spec.tsx b/tests/Keyboard.spec.tsx
index 73544b0f..30dfbcf2 100644
--- a/tests/Keyboard.spec.tsx
+++ b/tests/Keyboard.spec.tsx
@@ -1,10 +1,9 @@
 /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence, max-classes-per-file */
-import { fireEvent, render } from '@testing-library/react';
+import { fireEvent, render, act } from '@testing-library/react';
 import KeyCode from 'rc-util/lib/KeyCode';
 import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
 import React from 'react';
-import { act } from 'react-dom/test-utils';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 import { isActive, last } from './util';
 
 describe('Menu.Keyboard', () => {
@@ -47,11 +46,22 @@ describe('Menu.Keyboard', () => {
 
   it('no data-menu-id by init', () => {
     const { container } = render(
-      <Menu mode="inline" openKeys={['light']}>
-        <Menu.SubMenu key="light" title="Light">
-          <Menu.Item key="bamboo">Bamboo</Menu.Item>
-        </Menu.SubMenu>
-      </Menu>,
+      <Menu
+        mode="inline"
+        openKeys={['light']}
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+            children: [
+              {
+                key: 'bamboo',
+                label: 'Bamboo',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     expect(container.children).toMatchSnapshot();
@@ -65,11 +75,12 @@ describe('Menu.Keyboard', () => {
 
       render() {
         return (
-          <Menu>
-            {this.state.items.map(i => (
-              <MenuItem key={i}>{i}</MenuItem>
-            ))}
-          </Menu>
+          <Menu
+            items={this.state.items.map(i => ({
+              key: i,
+              label: i,
+            }))}
+          />
         );
       }
     }
@@ -95,13 +106,34 @@ describe('Menu.Keyboard', () => {
 
   it('Skip disabled item', () => {
     const { container } = render(
-      <Menu defaultActiveFirst>
-        <MenuItem disabled />
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem disabled />
-        <MenuItem key="2">2</MenuItem>
-        <MenuItem disabled />
-      </Menu>,
+      <Menu
+        defaultActiveFirst
+        items={[
+          {
+            key: 'disabled-1',
+            label: '',
+            disabled: true,
+          },
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: 'disabled-2',
+            label: '',
+            disabled: true,
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+          {
+            key: 'disabled-3',
+            label: '',
+            disabled: true,
+          },
+        ]}
+      />,
     );
 
     // Next item
@@ -124,11 +156,21 @@ describe('Menu.Keyboard', () => {
 
   it('Enter to open menu and active first item', () => {
     const { container } = render(
-      <Menu>
-        <SubMenu key="s1" title="submenu1">
-          <MenuItem key="s1-1">1</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        items={[
+          {
+            key: 's1',
+            type: 'submenu',
+            label: 'submenu1',
+            children: [
+              {
+                key: 's1-1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     // Active first sub menu
@@ -150,13 +192,30 @@ describe('Menu.Keyboard', () => {
     ) {
       it(`direction ${direction}`, () => {
         const { container, unmount } = render(
-          <Menu mode="vertical" direction={direction}>
-            <SubMenu key="bamboo" title="Bamboo">
-              <SubMenu key="light" title="Light">
-                <MenuItem key="little">Little</MenuItem>
-              </SubMenu>
-            </SubMenu>
-          </Menu>,
+          <Menu
+            mode="vertical"
+            direction={direction}
+            items={[
+              {
+                key: 'bamboo',
+                type: 'submenu',
+                label: 'Bamboo',
+                children: [
+                  {
+                    key: 'light',
+                    type: 'submenu',
+                    label: 'Light',
+                    children: [
+                      {
+                        key: 'little',
+                        label: 'Little',
+                      },
+                    ],
+                  },
+                ],
+              },
+            ]}
+          />,
         );
 
         // Active first
@@ -206,12 +265,26 @@ describe('Menu.Keyboard', () => {
 
   it('inline keyboard', () => {
     const { container } = render(
-      <Menu mode="inline">
-        <MenuItem key="light">Light</MenuItem>
-        <SubMenu key="bamboo" title="Bamboo">
-          <MenuItem key="little">Little</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="inline"
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+          {
+            key: 'bamboo',
+            type: 'submenu',
+            label: 'Bamboo',
+            children: [
+              {
+                key: 'little',
+                label: 'Little',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     // Nothing happen when no control key
@@ -244,10 +317,19 @@ describe('Menu.Keyboard', () => {
 
   it('Focus last one', () => {
     const { container } = render(
-      <Menu mode="inline">
-        <MenuItem key="light">Light</MenuItem>
-        <MenuItem key="bamboo">Bamboo</MenuItem>
-      </Menu>,
+      <Menu
+        mode="inline"
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+          },
+        ]}
+      />,
     );
 
     keyDown(container, KeyCode.UP);
@@ -256,11 +338,15 @@ describe('Menu.Keyboard', () => {
 
   it('Focus to link direct', () => {
     const { container } = render(
-      <Menu mode="inline">
-        <MenuItem key="light">
-          <a href="https://ant.design">Light</a>
-        </MenuItem>
-      </Menu>,
+      <Menu
+        mode="inline"
+        items={[
+          {
+            key: 'light',
+            label: <a href="https://ant.design">Light</a>,
+          },
+        ]}
+      />,
     );
 
     const focusSpy = jest.spyOn(container.querySelector('a'), 'focus');
@@ -271,9 +357,16 @@ describe('Menu.Keyboard', () => {
 
   it('no dead loop', async () => {
     const { container } = render(
-      <Menu mode="vertical" openKeys={['bamboo']}>
-        <MenuItem key="little">Little</MenuItem>
-      </Menu>,
+      <Menu
+        mode="vertical"
+        openKeys={['bamboo']}
+        items={[
+          {
+            key: 'little',
+            label: 'Little',
+          },
+        ]}
+      />,
     );
 
     keyDown(container, KeyCode.DOWN);
diff --git a/tests/Menu.spec.tsx b/tests/Menu.spec.tsx
index fc7326ef..4cc5d732 100644
--- a/tests/Menu.spec.tsx
+++ b/tests/Menu.spec.tsx
@@ -1,12 +1,11 @@
 /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence, max-classes-per-file */
 import type { MenuMode } from '@/interface';
-import { fireEvent, render } from '@testing-library/react';
+import { fireEvent, render, act } from '@testing-library/react';
 import KeyCode from 'rc-util/lib/KeyCode';
 import { resetWarned } from 'rc-util/lib/warning';
 import React from 'react';
-import { act } from 'react-dom/test-utils';
 import type { MenuRef } from '../src';
-import Menu, { Divider, MenuItem, MenuItemGroup, SubMenu } from '../src';
+import Menu from '../src';
 import { isActive, last } from './util';
 
 jest.mock('@rc-component/trigger', () => {
@@ -49,23 +48,57 @@ describe('Menu', () => {
           className="myMenu"
           openAnimation="fade"
           {...props}
-        >
-          <MenuItemGroup title="g1">
-            <MenuItem key="1">1</MenuItem>
-            <Divider />
-            <MenuItem key="2">2</MenuItem>
-          </MenuItemGroup>
-          <MenuItem key="3">3</MenuItem>
-          <MenuItemGroup title="g2">
-            <MenuItem key="4">4</MenuItem>
-            <MenuItem key="5" disabled>
-              5
-            </MenuItem>
-          </MenuItemGroup>
-          <SubMenu key={subKey} title="submenu">
-            <MenuItem key="6">6</MenuItem>
-          </SubMenu>
-        </Menu>
+          items={[
+            {
+              key: 'g1',
+              type: 'group',
+              label: 'g1',
+              children: [
+                {
+                  key: '1',
+                  label: '1',
+                },
+                {
+                  type: 'divider',
+                },
+                {
+                  key: '2',
+                  label: '2',
+                },
+              ],
+            },
+            {
+              key: '3',
+              label: '3',
+            },
+            {
+              key: 'g2',
+              type: 'group',
+              label: 'g2',
+              children: [
+                {
+                  key: '4',
+                  label: '4',
+                },
+                {
+                  key: '5',
+                  label: '5',
+                  disabled: true,
+                },
+              ],
+            },
+            {
+              key: subKey,
+              label: 'submenu',
+              children: [
+                {
+                  key: '6',
+                  label: '6',
+                },
+              ],
+            },
+          ]}
+        />
       );
     }
 
@@ -105,9 +138,16 @@ describe('Menu', () => {
       it(`${mode} menu that has a submenu with undefined children without error`, () => {
         expect(() =>
           render(
-            <Menu mode={mode}>
-              <SubMenu />
-            </Menu>,
+            <Menu
+              mode={mode}
+              items={[
+                {
+                  key: 'submenu',
+                  label: '',
+                  children: undefined,
+                },
+              ]}
+            />,
           ),
         ).not.toThrow();
       });
@@ -122,18 +162,40 @@ describe('Menu', () => {
 
     it('should support Fragment', () => {
       const { container } = render(
-        <Menu>
-          <SubMenu title="submenu">
-            <MenuItem key="6">6</MenuItem>
-          </SubMenu>
-          <MenuItem key="7">6</MenuItem>
-          <>
-            <SubMenu title="submenu">
-              <MenuItem key="8">6</MenuItem>
-            </SubMenu>
-            <MenuItem key="9">6</MenuItem>
-          </>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: 'submenu1',
+              type: 'submenu',
+              label: 'submenu',
+              children: [
+                {
+                  key: '6',
+                  label: '6',
+                },
+              ],
+            },
+            {
+              key: '7',
+              label: '6',
+            },
+            {
+              key: 'submenu2',
+              type: 'submenu',
+              label: 'submenu',
+              children: [
+                {
+                  key: '8',
+                  label: '6',
+                },
+              ],
+            },
+            {
+              key: '9',
+              label: '6',
+            },
+          ]}
+        />,
       );
       expect(container.children).toMatchSnapshot();
     });
@@ -142,17 +204,27 @@ describe('Menu', () => {
   describe('render role listbox', () => {
     function createMenu() {
       return (
-        <Menu className="myMenu" role="listbox">
-          <MenuItem key="1" role="option">
-            1
-          </MenuItem>
-          <MenuItem key="2" role="option">
-            2
-          </MenuItem>
-          <MenuItem key="3" role="option">
-            3
-          </MenuItem>
-        </Menu>
+        <Menu
+          className="myMenu"
+          role="listbox"
+          items={[
+            {
+              key: '1',
+              label: '1',
+              role: 'option',
+            },
+            {
+              key: '2',
+              label: '2',
+              role: 'option',
+            },
+            {
+              key: '3',
+              label: '3',
+              role: 'option',
+            },
+          ]}
+        />
       );
     }
 
@@ -164,10 +236,20 @@ describe('Menu', () => {
 
   it('set activeKey', () => {
     const genMenu = (props?) => (
-      <Menu activeKey="1" {...props}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>
+      <Menu
+        activeKey="1"
+        {...props}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />
     );
 
     const { container, rerender } = render(genMenu());
@@ -181,40 +263,40 @@ describe('Menu', () => {
 
   it('active first item', () => {
     const { container } = render(
-      <Menu defaultActiveFirst>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>,
+      <Menu
+        defaultActiveFirst
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />,
     );
     expect(container.querySelector('.rc-menu-item')).toHaveClass(
       'rc-menu-item-active',
     );
   });
 
-  it('should render none menu item children', () => {
-    expect(() => {
-      render(
-        <Menu activeKey="1">
-          <MenuItem key="1">1</MenuItem>
-          <MenuItem key="2">2</MenuItem>
-          string
-          {'string'}
-          {null}
-          {undefined}
-          {12345}
-          <div />
-          <input />
-        </Menu>,
-      );
-    }).not.toThrow();
-  });
-
   it('select multiple items', () => {
     const { container } = render(
-      <Menu multiple>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>,
+      <Menu
+        multiple
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />,
     );
 
     fireEvent.click(container.querySelector('.rc-menu-item'));
@@ -275,10 +357,20 @@ describe('Menu', () => {
 
   it('can be controlled by selectedKeys', () => {
     const genMenu = (props?) => (
-      <Menu selectedKeys={['1']} {...props}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>
+      <Menu
+        selectedKeys={['1']}
+        {...props}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />
     );
     const { container, rerender } = render(genMenu());
     expect(container.querySelector('li').className).toContain('-selected');
@@ -290,9 +382,15 @@ describe('Menu', () => {
 
   it('empty selectedKeys not to throw', () => {
     render(
-      <Menu selectedKeys={null}>
-        <MenuItem key="foo">foo</MenuItem>
-      </Menu>,
+      <Menu
+        selectedKeys={null}
+        items={[
+          {
+            key: 'foo',
+            label: 'foo',
+          },
+        ]}
+      />,
     );
   });
 
@@ -300,9 +398,17 @@ describe('Menu', () => {
     const onSelect = jest.fn();
 
     const genMenu = (props?) => (
-      <Menu onSelect={onSelect} selectedKeys={[]} {...props}>
-        <MenuItem key="bamboo">Bamboo</MenuItem>
-      </Menu>
+      <Menu
+        onSelect={onSelect}
+        selectedKeys={[]}
+        {...props}
+        items={[
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+          },
+        ]}
+      />
     );
 
     const { container, rerender } = render(genMenu());
@@ -321,10 +427,19 @@ describe('Menu', () => {
 
   it('select default item', () => {
     const { container } = render(
-      <Menu defaultSelectedKeys={['1']}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>,
+      <Menu
+        defaultSelectedKeys={['1']}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />,
     );
     expect(container.querySelector('li').className).toContain('-selected');
   });
@@ -333,10 +448,19 @@ describe('Menu', () => {
     // don't use selectedKeys as string
     // it is a compatible feature for https://github.com/ant-design/ant-design/issues/29429
     const { container } = render(
-      <Menu selectedKeys={('item_abc' as unknown) as string[]}>
-        <MenuItem key="item_a">1</MenuItem>
-        <MenuItem key="item_abc">2</MenuItem>
-      </Menu>,
+      <Menu
+        selectedKeys={'item_abc' as unknown as string[]}
+        items={[
+          {
+            key: 'item_a',
+            label: '1',
+          },
+          {
+            key: 'item_abc',
+            label: '2',
+          },
+        ]}
+      />,
     );
     expect(container.querySelector('li').className).not.toContain('-selected');
     expect(container.querySelectorAll('li')[1].className).toContain(
@@ -347,14 +471,34 @@ describe('Menu', () => {
   describe('openKeys', () => {
     it('can be controlled by openKeys', () => {
       const genMenu = (props?) => (
-        <Menu openKeys={['g1']} {...props}>
-          <Menu.SubMenu key="g1">
-            <MenuItem key="1">1</MenuItem>
-          </Menu.SubMenu>
-          <Menu.SubMenu key="g2">
-            <MenuItem key="2">2</MenuItem>
-          </Menu.SubMenu>
-        </Menu>
+        <Menu
+          openKeys={['g1']}
+          {...props}
+          items={[
+            {
+              key: 'g1',
+              type: 'submenu',
+              label: 'g1',
+              children: [
+                {
+                  key: '1',
+                  label: '1',
+                },
+              ],
+            },
+            {
+              key: 'g2',
+              type: 'submenu',
+              label: 'g2',
+              children: [
+                {
+                  key: '2',
+                  label: '2',
+                },
+              ],
+            },
+          ]}
+        />
       );
       const { container, rerender } = render(genMenu());
 
@@ -382,26 +526,47 @@ describe('Menu', () => {
           openKeys={undefined}
           selectedKeys={['1']}
           mode="inline"
-        >
-          <SubMenu title="1231">
-            <MenuItem>
-              <a>
-                <span>123123</span>
-              </a>
-            </MenuItem>
-          </SubMenu>
-        </Menu>,
+          items={[
+            {
+              key: 'submenu',
+              type: 'submenu',
+              label: '1231',
+              children: [
+                {
+                  key: 'item1',
+                  label: (
+                    <a>
+                      <span>123123</span>
+                    </a>
+                  ),
+                },
+              ],
+            },
+          ]}
+        />,
       );
       expect(container.innerHTML).toBeTruthy();
     });
 
     it('null of openKeys', () => {
       const { container } = render(
-        <Menu openKeys={null} mode="inline">
-          <SubMenu key="bamboo" title="Bamboo">
-            <MenuItem key="light">Light</MenuItem>
-          </SubMenu>
-        </Menu>,
+        <Menu
+          openKeys={null}
+          mode="inline"
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              label: 'Bamboo',
+              children: [
+                {
+                  key: 'light',
+                  label: 'Light',
+                },
+              ],
+            },
+          ]}
+        />,
       );
       expect(container.innerHTML).toBeTruthy();
     });
@@ -409,14 +574,33 @@ describe('Menu', () => {
 
   it('open default submenu', () => {
     const { container } = render(
-      <Menu defaultOpenKeys={['g1']}>
-        <SubMenu key="g1">
-          <MenuItem key="1">1</MenuItem>
-        </SubMenu>
-        <SubMenu key="g2">
-          <MenuItem key="2">2</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        defaultOpenKeys={['g1']}
+        items={[
+          {
+            key: 'g1',
+            type: 'submenu',
+            label: 'g1',
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+            ],
+          },
+          {
+            key: 'g2',
+            type: 'submenu',
+            label: 'g2',
+            children: [
+              {
+                key: '2',
+                label: '2',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     act(() => {
@@ -434,10 +618,19 @@ describe('Menu', () => {
   it('fires select event', () => {
     const handleSelect = jest.fn();
     const { container } = render(
-      <Menu onSelect={handleSelect}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>,
+      <Menu
+        onSelect={handleSelect}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />,
     );
     fireEvent.click(container.querySelector('.rc-menu-item'));
     expect(handleSelect.mock.calls[0][0].key).toBe('1');
@@ -450,13 +643,31 @@ describe('Menu', () => {
 
     const handleClick = jest.fn();
     const { container } = render(
-      <Menu onClick={handleClick} openKeys={['parent']}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-        <Menu.SubMenu key="parent">
-          <MenuItem key="3">3</MenuItem>
-        </Menu.SubMenu>
-      </Menu>,
+      <Menu
+        onClick={handleClick}
+        openKeys={['parent']}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+          {
+            key: 'parent',
+            type: 'submenu',
+            label: 'parent',
+            children: [
+              {
+                key: '3',
+                label: '3',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     act(() => {
@@ -482,10 +693,20 @@ describe('Menu', () => {
   it('fires deselect event', () => {
     const handleDeselect = jest.fn();
     const { container } = render(
-      <Menu multiple onDeselect={handleDeselect}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>,
+      <Menu
+        multiple
+        onDeselect={handleDeselect}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />,
     );
     const item = container.querySelector('.rc-menu-item');
     fireEvent.click(item);
@@ -495,24 +716,44 @@ describe('Menu', () => {
 
   it('active by mouse enter', () => {
     const { container } = render(
-      <Menu>
-        <MenuItem key="item1">item</MenuItem>
-        <MenuItem disabled>disabled</MenuItem>
-        <MenuItem key="item2">item2</MenuItem>
-      </Menu>,
+      <Menu
+        items={[
+          {
+            key: 'item1',
+            label: 'item',
+          },
+          {
+            key: 'disabled',
+            label: 'disabled',
+            disabled: true,
+          },
+          {
+            key: 'item2',
+            label: 'item2',
+          },
+        ]}
+      />,
     );
-    // wrapper.find('li').last().simulate('mouseEnter');
     fireEvent.mouseEnter(last(container.querySelectorAll('.rc-menu-item')));
-    // expect(wrapper.isActive(2)).toBeTruthy();
     isActive(container, 2);
   });
 
   it('active by key down', () => {
     const genMenu = (props?) => (
-      <Menu activeKey="1" {...props}>
-        <MenuItem key="1">1</MenuItem>
-        <MenuItem key="2">2</MenuItem>
-      </Menu>
+      <Menu
+        activeKey="1"
+        {...props}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: '2',
+            label: '2',
+          },
+        ]}
+      />
     );
     const { container, rerender } = render(genMenu());
 
@@ -530,9 +771,16 @@ describe('Menu', () => {
 
   it('defaultActiveFirst', () => {
     const { container } = render(
-      <Menu selectedKeys={['foo']} defaultActiveFirst>
-        <MenuItem key="foo">foo</MenuItem>
-      </Menu>,
+      <Menu
+        selectedKeys={['foo']}
+        defaultActiveFirst
+        items={[
+          {
+            key: 'foo',
+            label: 'foo',
+          },
+        ]}
+      />,
     );
     isActive(container, 0);
   });
@@ -550,12 +798,26 @@ describe('Menu', () => {
     };
 
     render(
-      <Menu builtinPlacements={builtinPlacements}>
-        <MenuItem>menuItem</MenuItem>
-        <SubMenu title="submenu">
-          <MenuItem>menuItem</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        builtinPlacements={builtinPlacements}
+        items={[
+          {
+            key: '1',
+            label: 'menuItem',
+          },
+          {
+            key: '2',
+            type: 'submenu',
+            label: 'submenu',
+            children: [
+              {
+                key: '3',
+                label: 'menuItem',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     expect(global.triggerProps.builtinPlacements.leftTop).toEqual(
@@ -572,11 +834,23 @@ describe('Menu', () => {
 
     it('defaultMotions should work correctly', () => {
       const genMenu = (props?) => (
-        <Menu mode="inline" defaultMotions={defaultMotions} {...props}>
-          <SubMenu key="bamboo">
-            <MenuItem key="light" />
-          </SubMenu>
-        </Menu>
+        <Menu
+          mode="inline"
+          defaultMotions={defaultMotions}
+          {...props}
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              children: [
+                {
+                  key: 'light',
+                  label: '',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { rerender } = render(genMenu());
@@ -605,11 +879,19 @@ describe('Menu', () => {
           defaultMotions={defaultMotions}
           motion={{ motionName: 'bambooLight' }}
           {...props}
-        >
-          <SubMenu key="bamboo">
-            <MenuItem key="light" />
-          </SubMenu>
-        </Menu>
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              children: [
+                {
+                  key: 'light',
+                  label: '',
+                },
+              ],
+            },
+          ]}
+        />
       );
       const { rerender } = render(genMenu());
 
@@ -628,11 +910,22 @@ describe('Menu', () => {
 
     it('inline does not affect vertical motion', () => {
       const genMenu = (props?) => (
-        <Menu defaultMotions={defaultMotions} {...props}>
-          <SubMenu key="bamboo">
-            <MenuItem key="light" />
-          </SubMenu>
-        </Menu>
+        <Menu
+          defaultMotions={defaultMotions}
+          {...props}
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              children: [
+                {
+                  key: 'light',
+                  label: '',
+                },
+              ],
+            },
+          ]}
+        />
       );
 
       const { rerender } = render(genMenu({ mode: 'vertical' }));
@@ -646,10 +939,20 @@ describe('Menu', () => {
   it('onMouseEnter should work', () => {
     const onMouseEnter = jest.fn();
     const { container } = render(
-      <Menu onMouseEnter={onMouseEnter} defaultSelectedKeys={['test1']}>
-        <MenuItem key="test1">Navigation One</MenuItem>
-        <MenuItem key="test2">Navigation Two</MenuItem>
-      </Menu>,
+      <Menu
+        onMouseEnter={onMouseEnter}
+        defaultSelectedKeys={['test1']}
+        items={[
+          {
+            key: 'test1',
+            label: 'Navigation One',
+          },
+          {
+            key: 'test2',
+            label: 'Navigation Two',
+          },
+        ]}
+      />,
     );
 
     fireEvent.mouseEnter(container.querySelector('.rc-menu-root'));
@@ -658,11 +961,23 @@ describe('Menu', () => {
 
   it('Nest children active should bump to top', async () => {
     const { container } = render(
-      <Menu activeKey="light" mode="vertical">
-        <SubMenu key="bamboo" title="Bamboo">
-          <MenuItem key="light">Light</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        activeKey="light"
+        mode="vertical"
+        items={[
+          {
+            key: 'bamboo',
+            type: 'submenu',
+            label: 'Bamboo',
+            children: [
+              {
+                key: 'light',
+                label: 'Light',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     expect(container.querySelector('.rc-menu-submenu-active')).toBeTruthy();
@@ -672,9 +987,14 @@ describe('Menu', () => {
     const errorSpy = jest.spyOn(console, 'error');
 
     const { unmount } = render(
-      <Menu>
-        <MenuItem key="bamboo">Bamboo</MenuItem>
-      </Menu>,
+      <Menu
+        items={[
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+          },
+        ]}
+      />,
     );
 
     unmount();
@@ -697,11 +1017,20 @@ describe('Menu', () => {
             mode="vertical"
             onOpenChange={onOpenChange}
             {...props}
-          >
-            <SubMenu key="bamboo" title="Bamboo">
-              <MenuItem key="light">Light</MenuItem>
-            </SubMenu>
-          </Menu>,
+            items={[
+              {
+                key: 'bamboo',
+                type: 'submenu',
+                label: 'Bamboo',
+                children: [
+                  {
+                    key: 'light',
+                    label: 'Light',
+                  },
+                ],
+              },
+            ]}
+          />,
         );
 
         // Open menu
@@ -723,11 +1052,24 @@ describe('Menu', () => {
       const onOpenChange = jest.fn();
 
       const { container } = render(
-        <Menu openKeys={['bamboo']} mode="inline" onOpenChange={onOpenChange}>
-          <SubMenu key="bamboo" title="Bamboo">
-            <MenuItem key="light">Light</MenuItem>
-          </SubMenu>
-        </Menu>,
+        <Menu
+          openKeys={['bamboo']}
+          mode="inline"
+          onOpenChange={onOpenChange}
+          items={[
+            {
+              key: 'bamboo',
+              type: 'submenu',
+              label: 'Bamboo',
+              children: [
+                {
+                  key: 'light',
+                  label: 'Light',
+                },
+              ],
+            },
+          ]}
+        />,
       );
 
       // Open menu
@@ -743,9 +1085,15 @@ describe('Menu', () => {
   it('should support ref', () => {
     const menuRef = React.createRef<MenuRef>();
     const { container } = render(
-      <Menu ref={menuRef}>
-        <MenuItem key="light">Light</MenuItem>
-      </Menu>,
+      <Menu
+        ref={menuRef}
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+        ]}
+      />,
     );
 
     expect(menuRef.current?.list).toBe(container.querySelector('ul'));
@@ -756,11 +1104,23 @@ describe('Menu', () => {
   it('should render a divider with role="separator"', () => {
     const menuRef = React.createRef<MenuRef>();
     const { container } = render(
-      <Menu ref={menuRef} activeKey="cat">
-        <MenuItem key="light">Light</MenuItem>
-        <Divider />
-        <MenuItem key="cat">Cat</MenuItem>
-      </Menu>,
+      <Menu
+        ref={menuRef}
+        activeKey="cat"
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+          {
+            type: 'divider',
+          },
+          {
+            key: 'cat',
+            label: 'Cat',
+          },
+        ]}
+      />,
     );
     // Get the divider element with the rc-menu-item-divider class
     const divider = container.querySelector('.rc-menu-item-divider');
@@ -768,6 +1128,7 @@ describe('Menu', () => {
     // Assert that the divider element with rc-menu-item-divider class has role="separator"
     expect(divider).toHaveAttribute('role', 'separator');
   });
+
   it('expandIcon should be hidden when setting null or false', () => {
     const App = ({
       expand,
@@ -776,18 +1137,46 @@ describe('Menu', () => {
       expand?: React.ReactNode;
       subExpand?: React.ReactNode;
     }) => (
-      <Menu expandIcon={expand}>
-        <SubMenu title="sub menu" key="1" expandIcon={subExpand}>
-          <MenuItem key="1-1">0-1</MenuItem>
-          <MenuItem key="1-2">0-2</MenuItem>
-        </SubMenu>
-        ,
-        <SubMenu title="sub menu2" key="2">
-          <MenuItem key="2-1">0-1</MenuItem>
-          <MenuItem key="2-2">0-2</MenuItem>
-        </SubMenu>
-        ,<MenuItem key="cat">Cat</MenuItem>
-      </Menu>
+      <Menu
+        expandIcon={expand}
+        items={[
+          {
+            key: '1',
+            type: 'submenu',
+            label: 'sub menu',
+            expandIcon: subExpand,
+            children: [
+              {
+                key: '1-1',
+                label: '0-1',
+              },
+              {
+                key: '1-2',
+                label: '0-2',
+              },
+            ],
+          },
+          {
+            key: '2',
+            type: 'submenu',
+            label: 'sub menu2',
+            children: [
+              {
+                key: '2-1',
+                label: '0-1',
+              },
+              {
+                key: '2-2',
+                label: '0-2',
+              },
+            ],
+          },
+          {
+            key: 'cat',
+            label: 'Cat',
+          },
+        ]}
+      />
     );
 
     const { container, rerender } = render(
diff --git a/tests/MenuItem.spec.tsx b/tests/MenuItem.spec.tsx
index d5cc0d12..18371353 100644
--- a/tests/MenuItem.spec.tsx
+++ b/tests/MenuItem.spec.tsx
@@ -2,7 +2,7 @@
 import { fireEvent, render } from '@testing-library/react';
 import KeyCode from 'rc-util/lib/KeyCode';
 import React from 'react';
-import Menu, { MenuItem, MenuItemGroup, SubMenu } from '../src';
+import Menu from '../src';
 
 describe('MenuItem', () => {
   const subMenuIconText = 'SubMenuIcon';
@@ -27,9 +27,17 @@ describe('MenuItem', () => {
   describe('custom icon', () => {
     it('should render custom arrow icon correctly.', () => {
       const { container } = render(
-        <Menu mode="vertical" itemIcon={itemIcon} expandIcon={expandIcon}>
-          <MenuItem key="1">1</MenuItem>
-        </Menu>,
+        <Menu
+          mode="vertical"
+          itemIcon={itemIcon}
+          expandIcon={expandIcon}
+          items={[
+            {
+              key: '1',
+              label: '1',
+            },
+          ]}
+        />,
       );
       const menuItemText = container.querySelector('.rc-menu-item').textContent;
       expect(menuItemText).toEqual(`1${menuItemIconText}`);
@@ -38,12 +46,22 @@ describe('MenuItem', () => {
     it('should render custom arrow icon correctly (with children props).', () => {
       const targetText = 'target';
       const { container } = render(
-        <Menu mode="vertical" itemIcon={itemIcon} expandIcon={expandIcon}>
-          <MenuItem key="1" itemIcon={() => <span>{targetText}</span>}>
-            1
-          </MenuItem>
-          <MenuItem key="2">2</MenuItem>
-        </Menu>,
+        <Menu
+          mode="vertical"
+          itemIcon={itemIcon}
+          expandIcon={expandIcon}
+          items={[
+            {
+              key: '1',
+              label: '1',
+              itemIcon: () => <span>{targetText}</span>,
+            },
+            {
+              key: '2',
+              label: '2',
+            },
+          ]}
+        />,
       );
       const menuItemText = container.querySelector('.rc-menu-item').textContent;
       expect(menuItemText).toEqual(`1${targetText}`);
@@ -53,11 +71,16 @@ describe('MenuItem', () => {
   it('not fires select event when disabled', () => {
     const handleSelect = jest.fn();
     const { container } = render(
-      <Menu onSelect={handleSelect}>
-        <MenuItem disabled>
-          <span className="xx">Item content</span>
-        </MenuItem>
-      </Menu>,
+      <Menu
+        onSelect={handleSelect}
+        items={[
+          {
+            key: '1',
+            disabled: true,
+            label: <span className="xx">Item content</span>,
+          },
+        ]}
+      />,
     );
 
     fireEvent.click(container.querySelector('.xx'));
@@ -67,9 +90,16 @@ describe('MenuItem', () => {
   describe('menuItem events', () => {
     function renderMenu(props, itemProps) {
       return render(
-        <Menu {...props}>
-          <MenuItem key="light" {...itemProps} />
-        </Menu>,
+        <Menu
+          {...props}
+          items={[
+            {
+              key: 'light',
+              label: 'light',
+              ...itemProps,
+            },
+          ]}
+        />,
       );
     }
 
@@ -120,21 +150,42 @@ describe('MenuItem', () => {
       };
 
       const { container } = render(
-        <Menu mode="inline" activeKey="1" openKeys={['bamboo']}>
-          <MenuItem key="1" {...restProps}>
-            1
-          </MenuItem>
-          <SubMenu key="bamboo" {...restProps}>
-            <MenuItem key="2" {...restProps}>
-              3
-            </MenuItem>
-          </SubMenu>
-          <MenuItemGroup {...restProps}>
-            <MenuItem key="3" {...restProps}>
-              4
-            </MenuItem>
-          </MenuItemGroup>
-        </Menu>,
+        <Menu
+          mode="inline"
+          activeKey="1"
+          openKeys={['bamboo']}
+          items={[
+            {
+              key: '1',
+              label: '1',
+              ...restProps,
+            },
+            {
+              key: 'bamboo',
+              label: 'bamboo',
+              type: 'submenu',
+              ...restProps,
+              children: [
+                {
+                  key: '2',
+                  label: '3',
+                  ...restProps,
+                },
+              ],
+            },
+            {
+              type: 'group',
+              ...restProps,
+              children: [
+                {
+                  key: '3',
+                  label: '4',
+                  ...restProps,
+                },
+              ],
+            },
+          ]}
+        />,
       );
 
       expect(container.children).toMatchSnapshot();
@@ -153,9 +204,15 @@ describe('MenuItem', () => {
   describe('overwrite default role', () => {
     it('should set role to none if null', () => {
       const { container } = render(
-        <Menu>
-          <MenuItem role={null}>test</MenuItem>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: '1',
+              label: 'test',
+              role: null,
+            },
+          ]}
+        />,
       );
 
       expect(container.querySelector('li')).toMatchSnapshot();
@@ -163,9 +220,15 @@ describe('MenuItem', () => {
 
     it('should set role to none if none', () => {
       const { container } = render(
-        <Menu>
-          <MenuItem role="none">test</MenuItem>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: '1',
+              label: 'test',
+              role: 'none',
+            },
+          ]}
+        />,
       );
 
       expect(container.querySelector('li')).toMatchSnapshot();
@@ -173,9 +236,15 @@ describe('MenuItem', () => {
 
     it('should set role to listitem', () => {
       const { container } = render(
-        <Menu>
-          <MenuItem role="listitem">test</MenuItem>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: '1',
+              label: 'test',
+              role: 'listitem',
+            },
+          ]}
+        />,
       );
 
       expect(container.querySelector('li')).toMatchSnapshot();
@@ -183,9 +252,15 @@ describe('MenuItem', () => {
 
     it('should set role to option', () => {
       const { container } = render(
-        <Menu>
-          <MenuItem role="option">test</MenuItem>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: '1',
+              label: 'test',
+              role: 'option',
+            },
+          ]}
+        />,
       );
 
       expect(container.querySelector('li')).toMatchSnapshot();
diff --git a/tests/Private.spec.tsx b/tests/Private.spec.tsx
index 06bdac9b..4f426afe 100644
--- a/tests/Private.spec.tsx
+++ b/tests/Private.spec.tsx
@@ -2,7 +2,7 @@
 import { render } from '@testing-library/react';
 import classnames from 'classnames';
 import React from 'react';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 
 describe('Private Props', () => {
   it('_internalRenderMenuItem', () => {
@@ -13,9 +13,13 @@ describe('Private Props', () => {
             className: classnames(node.props.className, 'inject-cls'),
           })
         }
-      >
-        <MenuItem key="1">1</MenuItem>
-      </Menu>,
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+        ]}
+      />,
     );
 
     expect(container.querySelector('.inject-cls')).toBeTruthy();
@@ -31,11 +35,20 @@ describe('Private Props', () => {
             className: classnames(node.props.className, 'inject-cls'),
           })
         }
-      >
-        <SubMenu key="1" title="1">
-          <MenuItem key="1-1">1-1</MenuItem>
-        </SubMenu>
-      </Menu>,
+        items={[
+          {
+            key: '1',
+            type: 'submenu',
+            label: '1',
+            children: [
+              {
+                key: '1-1',
+                label: '1-1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     expect(container.querySelector('.inject-cls')).toBeTruthy();
diff --git a/tests/React18.spec.tsx b/tests/React18.spec.tsx
index b505027d..51bfdd2d 100644
--- a/tests/React18.spec.tsx
+++ b/tests/React18.spec.tsx
@@ -2,7 +2,7 @@
 import { act, render } from '@testing-library/react';
 import React from 'react';
 import type { MenuProps } from '../src';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 
 describe('React18', () => {
   function runAllTimer() {
@@ -24,17 +24,44 @@ describe('React18', () => {
   function createMenu(props?: MenuProps) {
     return (
       <React.StrictMode>
-        <Menu {...props}>
-          <SubMenu key="s1" title="submenu1">
-            <MenuItem key="s1-1">1</MenuItem>
-            <SubMenu key="s1-2" title="submenu1-1">
-              <MenuItem key="s1-2-1">2</MenuItem>
-            </SubMenu>
-          </SubMenu>
-          <SubMenu key="s2" title="submenu2">
-            <MenuItem key="s2-2">2</MenuItem>
-          </SubMenu>
-        </Menu>
+        <Menu
+          {...props}
+          items={[
+            {
+              key: 's1',
+              label: 'submenu1',
+              type: 'submenu',
+              children: [
+                {
+                  key: 's1-1',
+                  label: '1',
+                },
+                {
+                  key: 's1-2',
+                  label: 'submenu1-1',
+                  type: 'submenu',
+                  children: [
+                    {
+                      key: 's1-2-1',
+                      label: '2',
+                    },
+                  ],
+                },
+              ],
+            },
+            {
+              key: 's2',
+              label: 'submenu2',
+              type: 'submenu',
+              children: [
+                {
+                  key: 's2-2',
+                  label: '2',
+                },
+              ],
+            },
+          ]}
+        />
       </React.StrictMode>
     );
   }
diff --git a/tests/Responsive.spec.tsx b/tests/Responsive.spec.tsx
index 9d1e6ff6..acaa3705 100644
--- a/tests/Responsive.spec.tsx
+++ b/tests/Responsive.spec.tsx
@@ -4,7 +4,7 @@ import ResizeObserver from 'rc-resize-observer';
 import KeyCode from 'rc-util/lib/KeyCode';
 import { spyElementPrototype } from 'rc-util/lib/test/domHook';
 import React from 'react';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 import { OVERFLOW_KEY } from '../src/hooks/useKeyRecords';
 import { last } from './util';
 
@@ -84,11 +84,25 @@ describe('Menu.Responsive', () => {
 
   it('ssr render full', () => {
     const { container } = render(
-      <Menu mode="horizontal">
-        <MenuItem key="light">Light</MenuItem>
-        <SubMenu key="bamboo">Bamboo</SubMenu>
-        <MenuItem key="little">Little</MenuItem>
-      </Menu>,
+      <Menu
+        mode="horizontal"
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+            type: 'submenu',
+            children: [],
+          },
+          {
+            key: 'little',
+            label: 'Little',
+          },
+        ]}
+      />,
     );
 
     expect(container.children).toMatchSnapshot();
@@ -103,13 +117,28 @@ describe('Menu.Responsive', () => {
         activeKey="little"
         onOpenChange={onOpenChange}
         {...props}
-      >
-        <MenuItem key="light">Light</MenuItem>
-        <MenuItem key="bamboo">Bamboo</MenuItem>
-        <SubMenu key="home" title="Home">
-          <MenuItem key="little">Little</MenuItem>
-        </SubMenu>
-      </Menu>
+        items={[
+          {
+            key: 'light',
+            label: 'Light',
+          },
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+          },
+          {
+            key: 'home',
+            label: 'Home',
+            type: 'submenu',
+            children: [
+              {
+                key: 'little',
+                label: 'Little',
+              },
+            ],
+          },
+        ]}
+      />
     );
 
     const { container, rerender } = render(genMenu());
@@ -150,13 +179,6 @@ describe('Menu.Responsive', () => {
       });
     spy.mockRestore();
 
-    // Should show the rest icon
-    // expect(
-    //   last(container.querySelectorAll('.rc-menu-overflow-item-rest')),
-    // ).not.toHaveStyle({
-    //   opacity: '0',
-    // });
-
     // Should set active on rest
     expect(
       last(container.querySelectorAll('.rc-menu-overflow-item-rest')),
diff --git a/tests/SubMenu.spec.tsx b/tests/SubMenu.spec.tsx
index f77e6d76..dd3950d7 100644
--- a/tests/SubMenu.spec.tsx
+++ b/tests/SubMenu.spec.tsx
@@ -2,7 +2,7 @@
 import { act, fireEvent, render } from '@testing-library/react';
 import { resetWarned } from 'rc-util/lib/warning';
 import React from 'react';
-import Menu, { MenuItem, SubMenu } from '../src';
+import Menu from '../src';
 import { isActive, last } from './util';
 
 jest.mock('@rc-component/trigger', () => {
@@ -48,17 +48,44 @@ describe('SubMenu', () => {
 
   function createMenu(props?) {
     return (
-      <Menu {...props}>
-        <SubMenu key="s1" title="submenu1">
-          <MenuItem key="s1-1">1</MenuItem>
-          <SubMenu key="s1-2" title="submenu1-1">
-            <MenuItem key="s1-2-1">2</MenuItem>
-          </SubMenu>
-        </SubMenu>
-        <SubMenu key="s2" title="submenu2">
-          <MenuItem key="s2-2">2</MenuItem>
-        </SubMenu>
-      </Menu>
+      <Menu
+        {...props}
+        items={[
+          {
+            key: 's1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: 's1-1',
+                label: '1',
+              },
+              {
+                key: 's1-2',
+                label: 'submenu1-1',
+                type: 'submenu',
+                children: [
+                  {
+                    key: 's1-2-1',
+                    label: '2',
+                  },
+                ],
+              },
+            ],
+          },
+          {
+            key: 's2',
+            label: 'submenu2',
+            type: 'submenu',
+            children: [
+              {
+                key: 's2-2',
+                label: '2',
+              },
+            ],
+          },
+        ]}
+      />
     );
   }
 
@@ -68,11 +95,23 @@ describe('SubMenu', () => {
 
   it("don't show submenu when disabled", () => {
     const { container } = render(
-      <Menu mode="vertical">
-        <SubMenu key="s" title="submenu" disabled>
-          <MenuItem key="1">1</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="vertical"
+        items={[
+          {
+            key: 's',
+            label: 'submenu',
+            type: 'submenu',
+            disabled: true,
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
     fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title'));
 
@@ -81,11 +120,24 @@ describe('SubMenu', () => {
 
   it('offsets the submenu popover', () => {
     render(
-      <Menu mode="horizontal" disabledOverflow>
-        <SubMenu key="s" title="submenu" popupOffset={[0, 15]}>
-          <MenuItem key="1">1</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="horizontal"
+        disabledOverflow
+        items={[
+          {
+            key: 's',
+            label: 'submenu',
+            type: 'submenu',
+            popupOffset: [0, 15],
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     const { popupAlign } = global.triggerProps;
@@ -98,12 +150,24 @@ describe('SubMenu', () => {
         mode="vertical"
         itemIcon={itemIcon}
         expandIcon={<span>SubMenuIconNode</span>}
-      >
-        <SubMenu key="s" title="submenu">
-          <MenuItem key="1">1</MenuItem>
-          <MenuItem key="2">2</MenuItem>
-        </SubMenu>
-      </Menu>,
+        items={[
+          {
+            key: 's',
+            label: 'submenu',
+            type: 'submenu',
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+              {
+                key: '2',
+                label: '2',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     const wrapperWithExpandIconFunction = render(
@@ -111,12 +175,24 @@ describe('SubMenu', () => {
         mode="vertical"
         itemIcon={itemIcon}
         expandIcon={() => <span>SubMenuIconNode</span>}
-      >
-        <SubMenu key="s" title="submenu">
-          <MenuItem key="1">1</MenuItem>
-          <MenuItem key="2">2</MenuItem>
-        </SubMenu>
-      </Menu>,
+        items={[
+          {
+            key: 's',
+            label: 'submenu',
+            type: 'submenu',
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+              {
+                key: '2',
+                label: '2',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     const subMenuText = container.querySelector(
@@ -132,16 +208,25 @@ describe('SubMenu', () => {
 
   it('should Not render custom arrow icon in horizontal mode.', () => {
     const { container } = render(
-      <Menu mode="horizontal" disabledOverflow>
-        <SubMenu
-          key="s"
-          title="submenu"
-          itemIcon={itemIcon}
-          expandIcon={<span>SubMenuIconNode</span>}
-        >
-          <MenuItem key="1">1</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="horizontal"
+        disabledOverflow
+        items={[
+          {
+            key: 's',
+            label: 'submenu',
+            type: 'submenu',
+            itemIcon: itemIcon,
+            expandIcon: <span>SubMenuIconNode</span>,
+            children: [
+              {
+                key: '1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     const childText = container.querySelector(
@@ -178,11 +263,21 @@ describe('SubMenu', () => {
   describe('openSubMenuOnMouseEnter and closeSubMenuOnMouseLeave are true', () => {
     it('toggles when mouse enter and leave', () => {
       const { container } = render(
-        <Menu>
-          <SubMenu key="s1" title="submenu1">
-            <MenuItem key="s1-1">1</MenuItem>
-          </SubMenu>
-        </Menu>,
+        <Menu
+          items={[
+            {
+              key: 's1',
+              label: 'submenu1',
+              type: 'submenu',
+              children: [
+                {
+                  key: 's1-1',
+                  label: '1',
+                },
+              ],
+            },
+          ]}
+        />,
       );
 
       // Enter
@@ -222,89 +317,77 @@ describe('SubMenu', () => {
   it('fires openChange event', () => {
     const handleOpenChange = jest.fn();
     const { container } = render(
-      <Menu onOpenChange={handleOpenChange}>
-        <MenuItem key="1">1</MenuItem>
-        <SubMenu title="s1">
-          <MenuItem key="2">2</MenuItem>
-          <SubMenu title="s2">
-            <MenuItem key="3">3</MenuItem>
-          </SubMenu>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        onOpenChange={handleOpenChange}
+        items={[
+          {
+            key: '1',
+            label: '1',
+          },
+          {
+            key: 's1',
+            label: 's1',
+            type: 'submenu',
+            children: [
+              {
+                key: '2',
+                label: '2',
+              },
+              {
+                key: 's2',
+                label: 's2',
+                type: 'submenu',
+                children: [
+                  {
+                    key: '3',
+                    label: '3',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     // First
     fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title'));
     runAllTimer();
-    expect(handleOpenChange).toHaveBeenCalledWith(['tmp_key-1']);
+    expect(handleOpenChange).toHaveBeenCalledWith(['s1']);
 
     // Second
     fireEvent.mouseEnter(
       container.querySelectorAll('.rc-menu-submenu-title')[1],
     );
     runAllTimer();
-    expect(handleOpenChange).toHaveBeenCalledWith([
-      'tmp_key-1',
-      'tmp_key-tmp_key-1-1',
-    ]);
+    expect(handleOpenChange).toHaveBeenCalledWith(['s1', 's2']);
   });
 
   describe('undefined key', () => {
-    it('warning item', () => {
-      resetWarned();
-
-      const errorSpy = jest
-        .spyOn(console, 'error')
-        .mockImplementation(() => {});
-
-      render(
-        <Menu>
-          <MenuItem>1</MenuItem>
-        </Menu>,
-      );
-
-      expect(errorSpy).toHaveBeenCalledWith(
-        'Warning: MenuItem should not leave undefined `key`.',
-      );
-
-      errorSpy.mockRestore();
-    });
-
-    it('warning sub menu', () => {
-      resetWarned();
-
-      const errorSpy = jest
-        .spyOn(console, 'error')
-        .mockImplementation(() => {});
-
-      render(
-        <Menu>
-          <SubMenu />
-        </Menu>,
-      );
-
-      expect(errorSpy).toHaveBeenCalledWith(
-        'Warning: SubMenu should not leave undefined `key`.',
-      );
-
-      errorSpy.mockRestore();
-    });
-
     it('should not warning', () => {
       resetWarned();
-
+      const errors: any[] = [];
       const errorSpy = jest
         .spyOn(console, 'error')
-        .mockImplementation(() => {});
+        .mockImplementation((msg, ...args) => {
+          // Only collect non-act related warnings
+          if (!msg.includes('act(...)')) {
+            errors.push([msg, ...args]);
+          }
+        });
 
       render(
-        <Menu>
-          <Menu.Divider />
-        </Menu>,
+        <Menu
+          items={[
+            {
+              type: 'divider',
+            },
+          ]}
+        />,
       );
 
-      expect(errorSpy).not.toHaveBeenCalled();
-
+      // Check if there are any non-act related warnings
+      expect(errors).toHaveLength(0);
       errorSpy.mockRestore();
     });
   });
@@ -336,16 +419,24 @@ describe('SubMenu', () => {
       const onMouseEnter = jest.fn();
       const onMouseLeave = jest.fn();
       const { container } = render(
-        <Menu openKeys={['s1']}>
-          <SubMenu
-            key="s1"
-            title="submenu1"
-            onMouseEnter={onMouseEnter}
-            onMouseLeave={onMouseLeave}
-          >
-            <MenuItem key="s1-1">1</MenuItem>
-          </SubMenu>
-        </Menu>,
+        <Menu
+          openKeys={['s1']}
+          items={[
+            {
+              key: 's1',
+              label: 'submenu1',
+              type: 'submenu',
+              onMouseEnter,
+              onMouseLeave,
+              children: [
+                {
+                  key: 's1-1',
+                  label: '1',
+                },
+              ],
+            },
+          ]}
+        />,
       );
       fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title'));
       expect(onMouseEnter).toHaveBeenCalledTimes(1);
@@ -396,15 +487,24 @@ describe('SubMenu', () => {
   });
 
   it('should take style prop', () => {
-    const App = () => (
-      <Menu style={{ backgroundColor: 'black' }}>
-        <SubMenu key="s1" title="submenu1">
-          <MenuItem key="s1-1">1</MenuItem>
-        </SubMenu>
-      </Menu>
+    const { container } = render(
+      <Menu
+        style={{ backgroundColor: 'black' }}
+        items={[
+          {
+            key: 's1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: 's1-1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
-
-    const { container } = render(<App />);
     expect(container.querySelector('.rc-menu')).toHaveStyle({
       backgroundColor: 'black',
     });
@@ -412,11 +512,18 @@ describe('SubMenu', () => {
 
   it('not pass style into sub menu item', () => {
     const { container } = render(
-      <Menu mode="horizontal" style={{ background: 'green' }} disabledOverflow>
-        <MenuItem style={{ color: 'red' }} key="1">
-          1
-        </MenuItem>
-      </Menu>,
+      <Menu
+        mode="horizontal"
+        style={{ background: 'green' }}
+        disabledOverflow
+        items={[
+          {
+            key: '1',
+            label: '1',
+            style: { color: 'red' },
+          },
+        ]}
+      />,
     );
 
     expect(container.querySelector('.rc-menu-item')).toHaveStyle({
@@ -428,14 +535,35 @@ describe('SubMenu', () => {
     const onOpenChange = jest.fn();
 
     const { container } = render(
-      <Menu mode="inline" onOpenChange={onOpenChange}>
-        <SubMenu key="bamboo" title="Bamboo" disabled>
-          <MenuItem key="little">Little</MenuItem>
-        </SubMenu>
-        <SubMenu key="light" title="Light">
-          <MenuItem key="sub">Sub</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="inline"
+        onOpenChange={onOpenChange}
+        items={[
+          {
+            key: 'bamboo',
+            label: 'Bamboo',
+            type: 'submenu',
+            disabled: true,
+            children: [
+              {
+                key: 'little',
+                label: 'Little',
+              },
+            ],
+          },
+          {
+            key: 'light',
+            label: 'Light',
+            type: 'submenu',
+            children: [
+              {
+                key: 'sub',
+                label: 'Sub',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     // Disabled
@@ -449,11 +577,24 @@ describe('SubMenu', () => {
 
   it('popup className should correct', () => {
     const { container } = render(
-      <Menu mode="horizontal" openKeys={['light']} disabledOverflow>
-        <SubMenu key="light">
-          <SubMenu key="bamboo" />
-        </SubMenu>
-      </Menu>,
+      <Menu
+        mode="horizontal"
+        openKeys={['light']}
+        disabledOverflow
+        items={[
+          {
+            key: 'light',
+            type: 'submenu',
+            children: [
+              {
+                key: 'bamboo',
+                type: 'submenu',
+                children: [],
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     runAllTimer();
@@ -469,19 +610,34 @@ describe('SubMenu', () => {
 
   it('should support rootClassName', () => {
     const { container } = render(
-      <Menu rootClassName="custom-className" defaultOpenKeys={['1', '1-1']}>
-        <SubMenu key="1" title="submenu1">
-          <MenuItem key="1-1" role="option">
-            submenu7
-          </MenuItem>
-        </SubMenu>
-        <MenuItem key="2" role="option">
-          2
-        </MenuItem>
-        <MenuItem key="3" role="option">
-          3
-        </MenuItem>
-      </Menu>,
+      <Menu
+        rootClassName="custom-className"
+        defaultOpenKeys={['1', '1-1']}
+        items={[
+          {
+            key: '1',
+            label: 'submenu1',
+            type: 'submenu',
+            children: [
+              {
+                key: '1-1',
+                label: 'submenu7',
+                role: 'option',
+              },
+            ],
+          },
+          {
+            key: '2',
+            label: '2',
+            role: 'option',
+          },
+          {
+            key: '3',
+            label: '3',
+            role: 'option',
+          },
+        ]}
+      />,
     );
     expect(container.children).toMatchSnapshot();
 
@@ -508,15 +664,22 @@ describe('SubMenu', () => {
 
   it('submenu should support popupStyle', () => {
     const { container } = render(
-      <Menu>
-        <SubMenu
-          key="s1"
-          title="submenu1"
-          popupStyle={{ zIndex: 100, width: 150 }}
-        >
-          <MenuItem key="s1-1">1</MenuItem>
-        </SubMenu>
-      </Menu>,
+      <Menu
+        items={[
+          {
+            key: 's1',
+            label: 'submenu1',
+            type: 'submenu',
+            popupStyle: { zIndex: 100, width: 150 },
+            children: [
+              {
+                key: 's1-1',
+                label: '1',
+              },
+            ],
+          },
+        ]}
+      />,
     );
 
     fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title'));
diff --git a/tests/__snapshots__/Menu.spec.tsx.snap b/tests/__snapshots__/Menu.spec.tsx.snap
index 633a94e3..3e7344f5 100644
--- a/tests/__snapshots__/Menu.spec.tsx.snap
+++ b/tests/__snapshots__/Menu.spec.tsx.snap
@@ -134,11 +134,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         tabindex="-1"
         title="submenu"
@@ -249,11 +249,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         tabindex="-1"
         title="submenu"
@@ -368,11 +368,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         style="padding-left: 24px;"
         tabindex="-1"
@@ -489,11 +489,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         style="padding-right: 24px;"
         tabindex="-1"
@@ -526,11 +526,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-0-popup"
+        aria-controls="rc-menu-uuid-test-submenu1-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-0"
+        data-menu-id="rc-menu-uuid-test-submenu1"
         role="menuitem"
         tabindex="-1"
         title="submenu"
@@ -554,11 +554,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-2-popup"
+        aria-controls="rc-menu-uuid-test-submenu2-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-2"
+        data-menu-id="rc-menu-uuid-test-submenu2"
         role="menuitem"
         tabindex="-1"
         title="submenu"
@@ -676,11 +676,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         tabindex="-1"
         title="submenu"
@@ -791,11 +791,11 @@ HTMLCollection [
       role="none"
     >
       <div
-        aria-controls="rc-menu-uuid-test-tmp_key-3-popup"
+        aria-controls="rc-menu-uuid-test-tmp-3-popup"
         aria-expanded="false"
         aria-haspopup="true"
         class="rc-menu-submenu-title"
-        data-menu-id="rc-menu-uuid-test-tmp_key-3"
+        data-menu-id="rc-menu-uuid-test-tmp-3"
         role="menuitem"
         tabindex="-1"
         title="submenu"
diff --git a/tests/__snapshots__/MenuItem.spec.tsx.snap b/tests/__snapshots__/MenuItem.spec.tsx.snap
index 4d761f6b..94a0b593 100644
--- a/tests/__snapshots__/MenuItem.spec.tsx.snap
+++ b/tests/__snapshots__/MenuItem.spec.tsx.snap
@@ -52,7 +52,7 @@ exports[`MenuItem overwrite default role should set extra to option 1`] = `
 exports[`MenuItem overwrite default role should set role to listitem 1`] = `
 <li
   class="rc-menu-item"
-  data-menu-id="rc-menu-uuid-test-tmp_key-0"
+  data-menu-id="rc-menu-uuid-test-1"
   role="listitem"
   tabindex="-1"
 >
@@ -63,7 +63,7 @@ exports[`MenuItem overwrite default role should set role to listitem 1`] = `
 exports[`MenuItem overwrite default role should set role to none if none 1`] = `
 <li
   class="rc-menu-item"
-  data-menu-id="rc-menu-uuid-test-tmp_key-0"
+  data-menu-id="rc-menu-uuid-test-1"
   role="none"
   tabindex="-1"
 >
@@ -74,7 +74,7 @@ exports[`MenuItem overwrite default role should set role to none if none 1`] = `
 exports[`MenuItem overwrite default role should set role to none if null 1`] = `
 <li
   class="rc-menu-item"
-  data-menu-id="rc-menu-uuid-test-tmp_key-0"
+  data-menu-id="rc-menu-uuid-test-1"
   role="none"
   tabindex="-1"
 >
@@ -86,7 +86,7 @@ exports[`MenuItem overwrite default role should set role to option 1`] = `
 <li
   aria-selected="false"
   class="rc-menu-item"
-  data-menu-id="rc-menu-uuid-test-tmp_key-0"
+  data-menu-id="rc-menu-uuid-test-1"
   role="option"
   tabindex="-1"
 >
@@ -128,9 +128,9 @@ HTMLCollection [
         role="menuitem"
         style="padding-left: 24px;"
         tabindex="-1"
-        title="title"
+        title="bamboo"
       >
-        title
+        bamboo
         <i
           class="rc-menu-submenu-arrow"
         />
@@ -163,10 +163,7 @@ HTMLCollection [
       <div
         class="rc-menu-item-group-title"
         role="presentation"
-        title="title"
-      >
-        title
-      </div>
+      />
       <ul
         class="rc-menu-item-group-list"
         role="group"
diff --git a/tests/__snapshots__/Responsive.spec.tsx.snap b/tests/__snapshots__/Responsive.spec.tsx.snap
index 36cd20ab..79a2fc63 100644
--- a/tests/__snapshots__/Responsive.spec.tsx.snap
+++ b/tests/__snapshots__/Responsive.spec.tsx.snap
@@ -29,7 +29,9 @@ HTMLCollection [
         class="rc-menu-submenu-title"
         role="menuitem"
         tabindex="-1"
+        title="Bamboo"
       >
+        Bamboo
         <i
           class="rc-menu-submenu-arrow"
         />
@@ -69,8 +71,6 @@ HTMLCollection [
   <div
     aria-hidden="true"
     style="display: none;"
-  >
-    Bamboo
-  </div>,
+  />,
 ]
 `;