mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
refactor(Grid): rewrite with hook (#24976)
* refactor: hooks * fix: lint * update hooks * update ref
This commit is contained in:
parent
dd8e9f8568
commit
a3f1de3293
@ -41,3 +41,10 @@ exports[`Grid should render Row 1`] = `
|
|||||||
class="ant-row"
|
class="ant-row"
|
||||||
/>
|
/>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Grid when typeof gutter is object array in large screen 1`] = `
|
||||||
|
<div
|
||||||
|
class="ant-row"
|
||||||
|
style="margin-left:-20px;margin-right:-20px;margin-top:-200px;margin-bottom:200px"
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
@ -4,6 +4,7 @@ import { Col, Row } from '..';
|
|||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import useBreakpoint from '../hooks/useBreakpoint';
|
import useBreakpoint from '../hooks/useBreakpoint';
|
||||||
|
import ResponsiveObserve from '../../_util/responsiveObserve';
|
||||||
|
|
||||||
describe('Grid', () => {
|
describe('Grid', () => {
|
||||||
mountTest(Row);
|
mountTest(Row);
|
||||||
@ -24,7 +25,12 @@ describe('Grid', () => {
|
|||||||
|
|
||||||
it('when typeof gutter is object', () => {
|
it('when typeof gutter is object', () => {
|
||||||
const wrapper = mount(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
|
const wrapper = mount(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
|
||||||
expect(wrapper.instance().getGutter()).toEqual([8, 0]);
|
expect(wrapper.find('div').first().props().style).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
marginLeft: -4,
|
||||||
|
marginRight: -4,
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('when typeof gutter is object array', () => {
|
it('when typeof gutter is object array', () => {
|
||||||
@ -36,11 +42,16 @@ describe('Grid', () => {
|
|||||||
]}
|
]}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.instance().getGutter()).toEqual([8, 8]);
|
expect(wrapper.find('div').first().props().style).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
marginLeft: -4,
|
||||||
|
marginRight: -4,
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('when typeof gutter is object array in large screen', () => {
|
it('when typeof gutter is object array in large screen', () => {
|
||||||
const wrapper = mount(
|
const wrapper = render(
|
||||||
<Row
|
<Row
|
||||||
gutter={[
|
gutter={[
|
||||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||||
@ -48,10 +59,7 @@ describe('Grid', () => {
|
|||||||
]}
|
]}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
wrapper.setState({
|
expect(wrapper).toMatchSnapshot();
|
||||||
screens: { md: true, lg: true, xl: true },
|
|
||||||
});
|
|
||||||
expect(wrapper.instance().getGutter()).toEqual([40, 400]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders wrapped Col correctly', () => {
|
it('renders wrapped Col correctly', () => {
|
||||||
@ -68,10 +76,10 @@ describe('Grid', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('when component has been unmounted, componentWillUnmount should be called', () => {
|
it('when component has been unmounted, componentWillUnmount should be called', () => {
|
||||||
const wrapper = mount(<Row />);
|
const Unmount = jest.spyOn(ResponsiveObserve, 'unsubscribe');
|
||||||
const willUnmount = jest.spyOn(wrapper.instance(), 'componentWillUnmount');
|
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
expect(willUnmount).toHaveBeenCalled();
|
expect(Unmount).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work correct when gutter is object', () => {
|
it('should work correct when gutter is object', () => {
|
||||||
|
@ -44,9 +44,8 @@ function parseFlex(flex: FlexType): string {
|
|||||||
return flex;
|
return flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Col extends React.Component<ColProps, {}> {
|
const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
||||||
renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
const renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||||
const { props } = this;
|
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
span,
|
span,
|
||||||
@ -123,7 +122,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...others} style={mergedStyle} className={classes}>
|
<div {...others} style={mergedStyle} className={classes} ref={ref}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -132,7 +131,9 @@ export default class Col extends React.Component<ColProps, {}> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
return <ConfigConsumer>{renderCol}</ConfigConsumer>;
|
||||||
return <ConfigConsumer>{this.renderCol}</ConfigConsumer>;
|
});
|
||||||
}
|
|
||||||
}
|
Col.displayName = 'Col';
|
||||||
|
|
||||||
|
export default Col;
|
||||||
|
@ -20,48 +20,37 @@ export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
|||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RowState {
|
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||||
screens: ScreenMap;
|
const [screens, setScreens] = React.useState<ScreenMap>({
|
||||||
}
|
xs: true,
|
||||||
|
sm: true,
|
||||||
|
md: true,
|
||||||
|
lg: true,
|
||||||
|
xl: true,
|
||||||
|
xxl: true,
|
||||||
|
});
|
||||||
|
const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>();
|
||||||
|
gutterRef.current = props.gutter;
|
||||||
|
|
||||||
export default class Row extends React.Component<RowProps, RowState> {
|
React.useEffect(() => {
|
||||||
static defaultProps = {
|
const token = ResponsiveObserve.subscribe(screen => {
|
||||||
gutter: 0,
|
const currentGutter = gutterRef.current || 0;
|
||||||
};
|
|
||||||
|
|
||||||
state: RowState = {
|
|
||||||
screens: {
|
|
||||||
xs: true,
|
|
||||||
sm: true,
|
|
||||||
md: true,
|
|
||||||
lg: true,
|
|
||||||
xl: true,
|
|
||||||
xxl: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
token: number;
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.token = ResponsiveObserve.subscribe(screens => {
|
|
||||||
const { gutter } = this.props;
|
|
||||||
if (
|
if (
|
||||||
(!Array.isArray(gutter) && typeof gutter === 'object') ||
|
(!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
|
||||||
(Array.isArray(gutter) && (typeof gutter[0] === 'object' || typeof gutter[1] === 'object'))
|
(Array.isArray(currentGutter) &&
|
||||||
|
(typeof currentGutter[0] === 'object' || typeof currentGutter[1] === 'object'))
|
||||||
) {
|
) {
|
||||||
this.setState({ screens });
|
setScreens(screen);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
return () => {
|
||||||
|
ResponsiveObserve.unsubscribe(token);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
componentWillUnmount() {
|
const getGutter = (): [number, number] => {
|
||||||
ResponsiveObserve.unsubscribe(this.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
getGutter(): [number, number] {
|
|
||||||
const results: [number, number] = [0, 0];
|
const results: [number, number] = [0, 0];
|
||||||
const { gutter } = this.props;
|
const { gutter = 0 } = props;
|
||||||
const { screens } = this.state;
|
|
||||||
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
||||||
normalizedGutter.forEach((g, index) => {
|
normalizedGutter.forEach((g, index) => {
|
||||||
if (typeof g === 'object') {
|
if (typeof g === 'object') {
|
||||||
@ -77,9 +66,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
};
|
||||||
|
|
||||||
renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
const renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
justify,
|
justify,
|
||||||
@ -88,9 +77,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
|||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
...others
|
...others
|
||||||
} = this.props;
|
} = props;
|
||||||
const prefixCls = getPrefixCls('row', customizePrefixCls);
|
const prefixCls = getPrefixCls('row', customizePrefixCls);
|
||||||
const gutter = this.getGutter();
|
const gutter = getGutter();
|
||||||
const classes = classNames(
|
const classes = classNames(
|
||||||
prefixCls,
|
prefixCls,
|
||||||
{
|
{
|
||||||
@ -120,14 +109,16 @@ export default class Row extends React.Component<RowProps, RowState> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RowContext.Provider value={{ gutter }}>
|
<RowContext.Provider value={{ gutter }}>
|
||||||
<div {...otherProps} className={classes} style={rowStyle}>
|
<div {...otherProps} className={classes} style={rowStyle} ref={ref}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</RowContext.Provider>
|
</RowContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
return <ConfigConsumer>{renderRow}</ConfigConsumer>;
|
||||||
return <ConfigConsumer>{this.renderRow}</ConfigConsumer>;
|
});
|
||||||
}
|
|
||||||
}
|
Row.displayName = 'Row';
|
||||||
|
|
||||||
|
export default Row;
|
||||||
|
Loading…
Reference in New Issue
Block a user