fix: Refactor Menu related components life cycle methods (#15868)

* use state instead

* rollback demo markdown

* clean test

* sider context should be clean

* update test case

* fix test

* update debug desc

* add siderCollapsed into omit

* rm useless code
This commit is contained in:
zombieJ 2019-04-05 16:15:01 +08:00 committed by GitHub
parent 50deee55c3
commit 89dd827b7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 410 additions and 166 deletions

View File

@ -1,4 +1,6 @@
import createContext, { Context } from 'create-react-context';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { LayoutContext, LayoutContextProps } from './layout';
// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
@ -18,7 +20,6 @@ import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import omit from 'omit.js';
import * as PropTypes from 'prop-types';
import Icon from '../icon';
import isNumeric from '../_util/isNumeric';
@ -31,6 +32,13 @@ const dimensionMap = {
xxl: '1600px',
};
export interface SiderContextProps {
siderCollapsed?: boolean;
collapsedWidth?: string | number;
}
export const SiderContext: Context<SiderContextProps> = createContext({});
export type CollapseType = 'clickTrigger' | 'responsive';
export type SiderTheme = 'light' | 'dark';
@ -50,16 +58,14 @@ export interface SiderProps extends React.HTMLAttributes<HTMLDivElement> {
onBreakpoint?: (broken: boolean) => void;
}
type InternalSideProps = SiderProps & LayoutContextProps;
export interface SiderState {
collapsed?: boolean;
below: boolean;
belowShow?: boolean;
}
export interface SiderContext {
siderCollapsed: boolean;
}
const generateId = (() => {
let i = 0;
return (prefix: string = '') => {
@ -68,9 +74,7 @@ const generateId = (() => {
};
})();
class Sider extends React.Component<SiderProps, SiderState> {
static __ANT_LAYOUT_SIDER: any = true;
class InternalSider extends React.Component<InternalSideProps, SiderState> {
static defaultProps = {
collapsible: false,
defaultCollapsed: false,
@ -81,16 +85,7 @@ class Sider extends React.Component<SiderProps, SiderState> {
theme: 'dark' as SiderTheme,
};
static childContextTypes = {
siderCollapsed: PropTypes.bool,
collapsedWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
};
static contextTypes = {
siderHook: PropTypes.object,
};
static getDerivedStateFromProps(nextProps: SiderProps) {
static getDerivedStateFromProps(nextProps: InternalSideProps) {
if ('collapsed' in nextProps) {
return {
collapsed: nextProps.collapsed,
@ -99,12 +94,10 @@ class Sider extends React.Component<SiderProps, SiderState> {
return null;
}
context: any;
private mql: MediaQueryList;
private uniqueId: string;
constructor(props: SiderProps) {
constructor(props: InternalSideProps) {
super(props);
this.uniqueId = generateId('ant-sider-');
let matchMedia;
@ -126,21 +119,14 @@ class Sider extends React.Component<SiderProps, SiderState> {
};
}
getChildContext() {
return {
siderCollapsed: this.state.collapsed,
collapsedWidth: this.props.collapsedWidth,
};
}
componentDidMount() {
if (this.mql) {
this.mql.addListener(this.responsiveHandler);
this.responsiveHandler(this.mql);
}
if (this.context.siderHook) {
this.context.siderHook.addSider(this.uniqueId);
if (this.props.siderHook) {
this.props.siderHook.addSider(this.uniqueId);
}
}
@ -149,8 +135,8 @@ class Sider extends React.Component<SiderProps, SiderState> {
this.mql.removeListener(this.responsiveHandler as any);
}
if (this.context.siderHook) {
this.context.siderHook.removeSider(this.uniqueId);
if (this.props.siderHook) {
this.props.siderHook.removeSider(this.uniqueId);
}
}
@ -206,6 +192,7 @@ class Sider extends React.Component<SiderProps, SiderState> {
'onCollapse',
'breakpoint',
'onBreakpoint',
'siderHook',
]);
const rawWidth = this.state.collapsed ? collapsedWidth : width;
// use "px" as fallback unit for width
@ -262,10 +249,29 @@ class Sider extends React.Component<SiderProps, SiderState> {
};
render() {
return <ConfigConsumer>{this.renderSider}</ConfigConsumer>;
const { collapsed } = this.state;
const { collapsedWidth } = this.props;
return (
<SiderContext.Provider
value={{
siderCollapsed: collapsed,
collapsedWidth,
}}
>
<ConfigConsumer>{this.renderSider}</ConfigConsumer>
</SiderContext.Provider>
);
}
}
polyfill(Sider);
polyfill(InternalSider);
export default Sider;
export default class Sider extends React.Component {
render() {
return (
<LayoutContext.Consumer>
{(context: LayoutContextProps) => <InternalSider {...context} {...this.props} />}
</LayoutContext.Consumer>
);
}
}

View File

@ -1,3 +1,3 @@
import demoTest from '../../../tests/shared/demoTest';
demoTest('layout');
demoTest('layout', { skip: ['custom-trigger-debug.md'] });

View File

@ -91,9 +91,9 @@ describe('Layout', () => {
it('should be controlled by collapsed', () => {
const wrapper = mount(<Sider>Sider</Sider>);
expect(wrapper.instance().state.collapsed).toBe(false);
expect(wrapper.find('InternalSider').instance().state.collapsed).toBe(false);
wrapper.setProps({ collapsed: true });
expect(wrapper.instance().state.collapsed).toBe(true);
expect(wrapper.find('InternalSider').instance().state.collapsed).toBe(true);
});
it('should not add ant-layout-has-sider when `hasSider` is `false`', () => {

View File

@ -0,0 +1,125 @@
---
order: 99
title:
zh-CN: 自定义触发器 Debug
en-US: Custom trigger debug
debug: true
---
## zh-CN
修改内容前,请尝试此 Demo 查看样式是否抖动。
````jsx
import { Layout, Menu, Icon } from 'antd';
const { Header, Sider, Content } = Layout;
const SubMenu = Menu.SubMenu;
class SiderDemo extends React.Component {
state = {
collapsed: true,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
};
render() {
return (
<Layout>
<Sider trigger={null} collapsible collapsed={this.state.collapsed}>
<div className="logo" />
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['3']}
defaultOpenKeys={['sub1']}
>
<Menu.Item key="1">
<Icon type="pie-chart" />
<span>Option 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="desktop" />
<span>Option 2</span>
</Menu.Item>
<SubMenu
key="sub1"
title={
<span>
<Icon type="user" />
<span>User</span>
</span>
}
>
<Menu.Item key="3">Tom</Menu.Item>
<Menu.Item key="4">Bill</Menu.Item>
<Menu.Item key="5">Alex</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<Icon type="team" />
<span>Team</span>
</span>
}
>
<Menu.Item key="6">Team 1</Menu.Item>
<Menu.Item key="8">Team 2</Menu.Item>
</SubMenu>
<Menu.Item key="9">
<Icon type="file" />
<span>File</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Content
style={{
margin: '24px 16px',
padding: 24,
background: '#fff',
minHeight: 280,
}}
>
Content
</Content>
</Layout>
</Layout>
);
}
}
ReactDOM.render(<SiderDemo />, mountNode);
````
````css
#components-layout-demo-custom-trigger .trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color .3s;
}
#components-layout-demo-custom-trigger .trigger:hover {
color: #1890ff;
}
#components-layout-demo-custom-trigger .logo {
height: 32px;
background: rgba(255,255,255,.2);
margin: 16px;
}
````

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import createContext, { Context } from 'create-react-context';
import { SiderProps } from './Sider';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
@ -13,6 +13,19 @@ export interface BasicProps extends React.HTMLAttributes<HTMLDivElement> {
hasSider?: boolean;
}
export interface LayoutContextProps {
siderHook: {
addSider: (id: string) => void;
removeSider: (id: string) => void;
};
}
export const LayoutContext: Context<LayoutContextProps> = createContext({
siderHook: {
addSider: () => null,
removeSider: () => null,
},
});
interface BasicPropsWithTagName extends BasicProps {
tagName: 'header' | 'footer' | 'main' | 'section';
}
@ -52,35 +65,37 @@ interface BasicLayoutState {
}
class BasicLayout extends React.Component<BasicPropsWithTagName, BasicLayoutState> {
static childContextTypes = {
siderHook: PropTypes.object,
};
state = { siders: [] };
getChildContext() {
getSiderHook() {
return {
siderHook: {
addSider: (id: string) => {
this.setState(state => ({
siders: [...state.siders, id],
}));
},
removeSider: (id: string) => {
this.setState(state => ({
siders: state.siders.filter(currentId => currentId !== id),
}));
},
addSider: (id: string) => {
this.setState(state => ({
siders: [...state.siders, id],
}));
},
removeSider: (id: string) => {
this.setState(state => ({
siders: state.siders.filter(currentId => currentId !== id),
}));
},
};
}
render() {
const { prefixCls, className, children, hasSider, tagName, ...others } = this.props;
const { prefixCls, className, children, hasSider, tagName: Tag, ...others } = this.props;
const classString = classNames(className, prefixCls, {
[`${prefixCls}-has-sider`]:
typeof hasSider === 'boolean' ? hasSider : this.state.siders.length > 0,
});
return React.createElement(tagName, { className: classString, ...others }, children);
return (
<LayoutContext.Provider value={{ siderHook: this.getSiderHook() }}>
<Tag className={classString} {...others}>
{children}
</Tag>
</LayoutContext.Provider>
);
}
}

View File

@ -3,6 +3,8 @@ import * as PropTypes from 'prop-types';
import { SubMenu as RcSubMenu } from 'rc-menu';
import classNames from 'classnames';
import { MenuContext, MenuContextProps } from './index';
interface TitleEventEntity {
key: string;
domEvent: Event;
@ -25,7 +27,6 @@ class SubMenu extends React.Component<SubMenuProps, any> {
};
// fix issue:https://github.com/ant-design/ant-design/issues/8666
static isSubMenu = 1;
context: any;
private subMenu: any;
onKeyDown = (e: React.MouseEvent<HTMLElement>) => {
@ -38,13 +39,16 @@ class SubMenu extends React.Component<SubMenuProps, any> {
render() {
const { rootPrefixCls, className } = this.props;
const theme = this.context.antdMenuTheme;
return (
<RcSubMenu
{...this.props}
ref={this.saveSubMenu}
popupClassName={classNames(`${rootPrefixCls}-${theme}`, className)}
/>
<MenuContext.Consumer>
{({ antdMenuTheme }: MenuContextProps) => (
<RcSubMenu
{...this.props}
ref={this.saveSubMenu}
popupClassName={classNames(`${rootPrefixCls}-${antdMenuTheme}`, className)}
/>
)}
</MenuContext.Consumer>
);
}
}

View File

@ -0,0 +1,71 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Menu should controlled collapse work 1`] = `
<ul
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
>
<li
class="ant-menu-item"
role="menuitem"
style="padding-left: 24px;"
>
<i
aria-label="icon: pie-chart"
class="anticon anticon-pie-chart"
>
<svg
aria-hidden="true"
class=""
data-icon="pie-chart"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M864 518H506V160c0-4.4-3.6-8-8-8h-26a398.46 398.46 0 0 0-282.8 117.1 398.19 398.19 0 0 0-85.7 127.1A397.61 397.61 0 0 0 72 552a398.46 398.46 0 0 0 117.1 282.8c36.7 36.7 79.5 65.6 127.1 85.7A397.61 397.61 0 0 0 472 952a398.46 398.46 0 0 0 282.8-117.1c36.7-36.7 65.6-79.5 85.7-127.1A397.61 397.61 0 0 0 872 552v-26c0-4.4-3.6-8-8-8zM705.7 787.8A331.59 331.59 0 0 1 470.4 884c-88.1-.4-170.9-34.9-233.2-97.2C174.5 724.1 140 640.7 140 552c0-88.7 34.5-172.1 97.2-234.8 54.6-54.6 124.9-87.9 200.8-95.5V586h364.3c-7.7 76.3-41.3 147-96.6 201.8zM952 462.4l-2.6-28.2c-8.5-92.1-49.4-179-115.2-244.6A399.4 399.4 0 0 0 589 74.6L560.7 72c-4.7-.4-8.7 3.2-8.7 7.9V464c0 4.4 3.6 8 8 8l384-1c4.7 0 8.4-4 8-8.6zm-332.2-58.2V147.6a332.24 332.24 0 0 1 166.4 89.8c45.7 45.6 77 103.6 90 166.1l-256.4.7z"
/>
</svg>
</i>
<span>
Option 1
</span>
</li>
</ul>
`;
exports[`Menu should controlled collapse work 2`] = `
<ul
class="ant-menu ant-menu-light ant-menu-inline-collapsed ant-menu-root ant-menu-inline"
role="menu"
>
<li
class="ant-menu-item"
role="menuitem"
style="padding-left: 24px;"
>
<i
aria-label="icon: pie-chart"
class="anticon anticon-pie-chart"
>
<svg
aria-hidden="true"
class=""
data-icon="pie-chart"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M864 518H506V160c0-4.4-3.6-8-8-8h-26a398.46 398.46 0 0 0-282.8 117.1 398.19 398.19 0 0 0-85.7 127.1A397.61 397.61 0 0 0 72 552a398.46 398.46 0 0 0 117.1 282.8c36.7 36.7 79.5 65.6 127.1 85.7A397.61 397.61 0 0 0 472 952a398.46 398.46 0 0 0 282.8-117.1c36.7-36.7 65.6-79.5 85.7-127.1A397.61 397.61 0 0 0 872 552v-26c0-4.4-3.6-8-8-8zM705.7 787.8A331.59 331.59 0 0 1 470.4 884c-88.1-.4-170.9-34.9-233.2-97.2C174.5 724.1 140 640.7 140 552c0-88.7 34.5-172.1 97.2-234.8 54.6-54.6 124.9-87.9 200.8-95.5V586h364.3c-7.7 76.3-41.3 147-96.6 201.8zM952 462.4l-2.6-28.2c-8.5-92.1-49.4-179-115.2-244.6A399.4 399.4 0 0 0 589 74.6L560.7 72c-4.7-.4-8.7 3.2-8.7 7.9V464c0 4.4 3.6 8 8 8l384-1c4.7 0 8.4-4 8-8.6zm-332.2-58.2V147.6a332.24 332.24 0 0 1 166.4 89.8c45.7 45.6 77 103.6 90 166.1l-256.4.7z"
/>
</svg>
</i>
<span>
Option 1
</span>
</li>
</ul>
`;

View File

@ -556,37 +556,13 @@ describe('Menu', () => {
it('get correct animation type when switched from inline', () => {
const wrapper = mount(<Menu mode="inline" />);
wrapper.setProps({ mode: 'horizontal' });
expect(wrapper.instance().getMenuOpenAnimation('')).toBe('');
expect(wrapper.instance().switchingModeFromInline).toBe(false);
});
it('Menu should not shake when collapsed changed', () => {
const wrapper = mount(
<Menu
defaultSelectedKeys={['5']}
defaultOpenKeys={['sub1']}
mode="inline"
inlineCollapsed={false}
>
<SubMenu
key="sub1"
title={
<span>
<span>Navigation One</span>
</span>
}
>
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
</SubMenu>
</Menu>,
);
expect(wrapper.instance().contextSiderCollapsed).toBe(true);
wrapper.setProps({ inlineCollapsed: true });
expect(wrapper.instance().contextSiderCollapsed).toBe(false);
jest.runAllTimers();
wrapper.update();
expect(wrapper.instance().contextSiderCollapsed).toBe(false);
expect(
wrapper
.find('InternalMenu')
.instance()
.getMenuOpenAnimation(''),
).toBe('');
expect(wrapper.find('InternalMenu').state().switchingModeFromInline).toBe(false);
});
it('MenuItem should not render Tooltip when inlineCollapsed is false', () => {
@ -615,4 +591,21 @@ describe('Menu', () => {
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBe(0);
});
it('should controlled collapse work', () => {
const wrapper = mount(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1">
<Icon type="pie-chart" />
<span>Option 1</span>
</Menu.Item>
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ inlineCollapsed: true });
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -1,13 +1,15 @@
import * as React from 'react';
import RcMenu, { Divider, ItemGroup } from 'rc-menu';
import * as PropTypes from 'prop-types';
import createContext, { Context } from 'create-react-context';
import classNames from 'classnames';
import omit from 'omit.js';
import SubMenu from './SubMenu';
import Item from './MenuItem';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import animation from '../_util/openAnimation';
import warning from '../_util/warning';
import { polyfill } from 'react-lifecycles-compat';
import { SiderContext, SiderContextProps } from '../layout/Sider';
export interface SelectParam {
key: string;
@ -57,42 +59,70 @@ export interface MenuProps {
overflowedIndicator?: React.ReactNode;
}
type InternalMenuProps = MenuProps & SiderContextProps;
export interface MenuState {
openKeys: string[];
// This may be not best way since origin code use `this.switchingModeFromInline` to handle collapse management.
// But for current test, seems it's OK just use state.
switchingModeFromInline: boolean;
inlineOpenKeys: string[];
prevProps: InternalMenuProps;
}
class Menu extends React.Component<MenuProps, MenuState> {
static Divider = Divider;
static Item = Item;
static SubMenu = SubMenu;
static ItemGroup = ItemGroup;
export interface MenuContextProps {
inlineCollapsed: boolean;
antdMenuTheme?: MenuTheme;
}
export const MenuContext: Context<MenuContextProps> = createContext({
inlineCollapsed: false,
});
class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
static defaultProps: Partial<MenuProps> = {
className: '',
theme: 'light', // or dark
focusable: false,
};
static childContextTypes = {
inlineCollapsed: PropTypes.bool,
antdMenuTheme: PropTypes.string,
};
static contextTypes = {
siderCollapsed: PropTypes.bool,
collapsedWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
};
static getDerivedStateFromProps(nextProps: MenuProps) {
if ('openKeys' in nextProps) {
return { openKeys: nextProps.openKeys! };
static getDerivedStateFromProps(nextProps: InternalMenuProps, prevState: MenuState) {
const { prevProps } = prevState;
const newState: Partial<MenuState> = {
prevProps: nextProps,
};
if (prevProps.mode === 'inline' && nextProps.mode !== 'inline') {
newState.switchingModeFromInline = true;
}
return null;
if ('openKeys' in nextProps) {
newState.openKeys = nextProps.openKeys;
} else {
// [Legacy] Old code will return after `openKeys` changed.
// Not sure the reason, we should keep this logic still.
if (
(nextProps.inlineCollapsed && !prevProps.inlineCollapsed) ||
(nextProps.siderCollapsed && !prevProps.siderCollapsed)
) {
newState.switchingModeFromInline = true;
newState.inlineOpenKeys = prevState.openKeys;
newState.openKeys = [];
}
if (
(!nextProps.inlineCollapsed && prevProps.inlineCollapsed) ||
(!nextProps.siderCollapsed && prevProps.siderCollapsed)
) {
newState.openKeys = prevState.inlineOpenKeys;
newState.inlineOpenKeys = [];
}
}
return newState;
}
context: any;
switchingModeFromInline: boolean;
inlineOpenKeys: string[] = [];
contextSiderCollapsed: boolean = true;
constructor(props: MenuProps) {
constructor(props: InternalMenuProps) {
super(props);
warning(
@ -117,43 +147,18 @@ class Menu extends React.Component<MenuProps, MenuState> {
this.state = {
openKeys: openKeys || [],
switchingModeFromInline: false,
inlineOpenKeys: [],
prevProps: props,
};
}
getChildContext() {
return {
inlineCollapsed: this.getInlineCollapsed(),
antdMenuTheme: this.props.theme,
};
}
componentDidUpdate(prevProps: MenuProps) {
if (prevProps.mode === 'inline' && this.props.mode !== 'inline') {
this.switchingModeFromInline = true;
}
if (
(this.props.inlineCollapsed && !prevProps.inlineCollapsed) ||
(this.getInlineCollapsed() && this.contextSiderCollapsed)
) {
this.contextSiderCollapsed = false;
this.switchingModeFromInline = true;
this.inlineOpenKeys = this.state.openKeys;
this.setState({ openKeys: [] });
}
if (
(!this.props.inlineCollapsed && prevProps.inlineCollapsed) ||
(!this.getInlineCollapsed() && !this.contextSiderCollapsed)
) {
this.contextSiderCollapsed = true;
this.setState({ openKeys: this.inlineOpenKeys });
this.inlineOpenKeys = [];
}
}
restoreModeVerticalFromInline() {
if (this.switchingModeFromInline) {
this.switchingModeFromInline = false;
this.setState({});
const { switchingModeFromInline } = this.state;
if (switchingModeFromInline) {
this.setState({
switchingModeFromInline: false,
});
}
}
@ -175,7 +180,7 @@ class Menu extends React.Component<MenuProps, MenuState> {
// Fix SVGElement e.target.className.indexOf is not a function
// https://github.com/ant-design/ant-design/issues/15699
const { className } = e.target as (HTMLElement | SVGElement);
const { className } = e.target as HTMLElement | SVGElement;
// SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during an animation.
const classNameValue =
Object.prototype.toString.call(className) === '[object SVGAnimatedString]'
@ -216,7 +221,7 @@ class Menu extends React.Component<MenuProps, MenuState> {
getRealMenuMode() {
const inlineCollapsed = this.getInlineCollapsed();
if (this.switchingModeFromInline && inlineCollapsed) {
if (this.state.switchingModeFromInline && inlineCollapsed) {
return 'inline';
}
const { mode } = this.props;
@ -225,11 +230,8 @@ class Menu extends React.Component<MenuProps, MenuState> {
getInlineCollapsed() {
const { inlineCollapsed } = this.props;
if (this.context.siderCollapsed !== undefined) {
return this.context.siderCollapsed;
}
if (this.contextSiderCollapsed) {
return false;
if (this.props.siderCollapsed !== undefined) {
return this.props.siderCollapsed;
}
return inlineCollapsed;
}
@ -245,9 +247,12 @@ class Menu extends React.Component<MenuProps, MenuState> {
} else {
// When mode switch from inline
// submenu should hide without animation
if (this.switchingModeFromInline) {
if (this.state.switchingModeFromInline) {
menuOpenAnimation = '';
this.switchingModeFromInline = false;
this.setState({
switchingModeFromInline: false,
});
// this.switchingModeFromInline = false;
} else {
menuOpenAnimation = 'zoom-big';
}
@ -257,7 +262,8 @@ class Menu extends React.Component<MenuProps, MenuState> {
}
renderMenu = ({ getPopupContainer, getPrefixCls }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, className, theme } = this.props;
const { prefixCls: customizePrefixCls, className, theme, collapsedWidth } = this.props;
const passProps = omit(this.props, ['collapsedWidth', 'siderCollapsed']);
const menuMode = this.getRealMenuMode();
const menuOpenAnimation = this.getMenuOpenAnimation(menuMode!);
@ -282,7 +288,6 @@ class Menu extends React.Component<MenuProps, MenuState> {
}
// https://github.com/ant-design/ant-design/issues/8587
const { collapsedWidth } = this.context;
if (
this.getInlineCollapsed() &&
(collapsedWidth === 0 || collapsedWidth === '0' || collapsedWidth === '0px')
@ -293,7 +298,7 @@ class Menu extends React.Component<MenuProps, MenuState> {
return (
<RcMenu
getPopupContainer={getPopupContainer}
{...this.props}
{...passProps}
{...menuProps}
prefixCls={prefixCls}
onTransitionEnd={this.handleTransitionEnd}
@ -303,10 +308,33 @@ class Menu extends React.Component<MenuProps, MenuState> {
};
render() {
return <ConfigConsumer>{this.renderMenu}</ConfigConsumer>;
return (
<MenuContext.Provider
value={{
inlineCollapsed: this.getInlineCollapsed() || false,
antdMenuTheme: this.props.theme,
}}
>
<ConfigConsumer>{this.renderMenu}</ConfigConsumer>
</MenuContext.Provider>
);
}
}
polyfill(Menu);
polyfill(InternalMenu);
export default Menu;
// We should keep this as ref-able
export default class Menu extends React.Component<MenuProps, {}> {
static Divider = Divider;
static Item = Item;
static SubMenu = SubMenu;
static ItemGroup = ItemGroup;
render() {
return (
<SiderContext.Consumer>
{(context: SiderContextProps) => <InternalMenu {...this.props} {...context} />}
</SiderContext.Consumer>
);
}
}

View File

@ -2,4 +2,5 @@ import '../../style/index.less';
import './index.less';
// style dependencies
// deps-lint-skip: layout
import '../../tooltip/style';

View File

@ -483,6 +483,7 @@ exports[`Table.rowSelection render with default selection correctly 1`] = `
<ul
class="ant-dropdown-menu ant-table-selection-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
role="menu"
tabindex="0"
>
<li
class="ant-dropdown-menu-item"