mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-06 00:44:17 +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"
|
||||
/>
|
||||
`;
|
||||
|
||||
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 rtlTest from '../../../tests/shared/rtlTest';
|
||||
import useBreakpoint from '../hooks/useBreakpoint';
|
||||
import ResponsiveObserve from '../../_util/responsiveObserve';
|
||||
|
||||
describe('Grid', () => {
|
||||
mountTest(Row);
|
||||
@ -24,7 +25,12 @@ describe('Grid', () => {
|
||||
|
||||
it('when typeof gutter is object', () => {
|
||||
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', () => {
|
||||
@ -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', () => {
|
||||
const wrapper = mount(
|
||||
const wrapper = render(
|
||||
<Row
|
||||
gutter={[
|
||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||
@ -48,10 +59,7 @@ describe('Grid', () => {
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
wrapper.setState({
|
||||
screens: { md: true, lg: true, xl: true },
|
||||
});
|
||||
expect(wrapper.instance().getGutter()).toEqual([40, 400]);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders wrapped Col correctly', () => {
|
||||
@ -68,10 +76,10 @@ describe('Grid', () => {
|
||||
});
|
||||
|
||||
it('when component has been unmounted, componentWillUnmount should be called', () => {
|
||||
const wrapper = mount(<Row />);
|
||||
const willUnmount = jest.spyOn(wrapper.instance(), 'componentWillUnmount');
|
||||
const Unmount = jest.spyOn(ResponsiveObserve, 'unsubscribe');
|
||||
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
|
||||
wrapper.unmount();
|
||||
expect(willUnmount).toHaveBeenCalled();
|
||||
expect(Unmount).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should work correct when gutter is object', () => {
|
||||
|
@ -44,9 +44,8 @@ function parseFlex(flex: FlexType): string {
|
||||
return flex;
|
||||
}
|
||||
|
||||
export default class Col extends React.Component<ColProps, {}> {
|
||||
renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { props } = this;
|
||||
const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
||||
const renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
span,
|
||||
@ -123,7 +122,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
}
|
||||
|
||||
return (
|
||||
<div {...others} style={mergedStyle} className={classes}>
|
||||
<div {...others} style={mergedStyle} className={classes} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -132,7 +131,9 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderCol}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
return <ConfigConsumer>{renderCol}</ConfigConsumer>;
|
||||
});
|
||||
|
||||
Col.displayName = 'Col';
|
||||
|
||||
export default Col;
|
||||
|
@ -20,48 +20,37 @@ export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
export interface RowState {
|
||||
screens: ScreenMap;
|
||||
}
|
||||
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
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> {
|
||||
static defaultProps = {
|
||||
gutter: 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;
|
||||
React.useEffect(() => {
|
||||
const token = ResponsiveObserve.subscribe(screen => {
|
||||
const currentGutter = gutterRef.current || 0;
|
||||
if (
|
||||
(!Array.isArray(gutter) && typeof gutter === 'object') ||
|
||||
(Array.isArray(gutter) && (typeof gutter[0] === 'object' || typeof gutter[1] === 'object'))
|
||||
(!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
|
||||
(Array.isArray(currentGutter) &&
|
||||
(typeof currentGutter[0] === 'object' || typeof currentGutter[1] === 'object'))
|
||||
) {
|
||||
this.setState({ screens });
|
||||
setScreens(screen);
|
||||
}
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
ResponsiveObserve.unsubscribe(token);
|
||||
};
|
||||
}, []);
|
||||
|
||||
componentWillUnmount() {
|
||||
ResponsiveObserve.unsubscribe(this.token);
|
||||
}
|
||||
|
||||
getGutter(): [number, number] {
|
||||
const getGutter = (): [number, number] => {
|
||||
const results: [number, number] = [0, 0];
|
||||
const { gutter } = this.props;
|
||||
const { screens } = this.state;
|
||||
const { gutter = 0 } = props;
|
||||
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
||||
normalizedGutter.forEach((g, index) => {
|
||||
if (typeof g === 'object') {
|
||||
@ -77,9 +66,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
justify,
|
||||
@ -88,9 +77,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
style,
|
||||
children,
|
||||
...others
|
||||
} = this.props;
|
||||
} = props;
|
||||
const prefixCls = getPrefixCls('row', customizePrefixCls);
|
||||
const gutter = this.getGutter();
|
||||
const gutter = getGutter();
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
@ -120,14 +109,16 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
|
||||
return (
|
||||
<RowContext.Provider value={{ gutter }}>
|
||||
<div {...otherProps} className={classes} style={rowStyle}>
|
||||
<div {...otherProps} className={classes} style={rowStyle} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
</RowContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderRow}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
return <ConfigConsumer>{renderRow}</ConfigConsumer>;
|
||||
});
|
||||
|
||||
Row.displayName = 'Row';
|
||||
|
||||
export default Row;
|
||||
|
Loading…
Reference in New Issue
Block a user