refactor(grid): useContext and improve code (#27127)

This commit is contained in:
Tom Xu 2020-10-14 15:19:07 +08:00 committed by GitHub
parent c7e51aba13
commit f6769e3e94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 127 additions and 136 deletions

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import classNames from 'classnames';
import RowContext from './RowContext';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
// https://github.com/ant-design/ant-design/issues/14324
type ColSpanType = number | string;
@ -46,93 +46,89 @@ function parseFlex(flex: FlexType): string {
}
const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
const renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
span,
order,
offset,
push,
pull,
className,
children,
flex,
style,
...others
} = props;
const prefixCls = getPrefixCls('col', customizePrefixCls);
let sizeClassObj = {};
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach(size => {
let sizeProps: ColSize = {};
const propSize = (props as any)[size];
if (typeof propSize === 'number') {
sizeProps.span = propSize;
} else if (typeof propSize === 'object') {
sizeProps = propSize || {};
}
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const { gutter } = React.useContext(RowContext);
delete (others as any)[size];
const {
prefixCls: customizePrefixCls,
span,
order,
offset,
push,
pull,
className,
children,
flex,
style,
...others
} = props;
sizeClassObj = {
...sizeClassObj,
[`${prefixCls}-${size}-${sizeProps.span}`]: sizeProps.span !== undefined,
[`${prefixCls}-${size}-order-${sizeProps.order}`]: sizeProps.order || sizeProps.order === 0,
[`${prefixCls}-${size}-offset-${sizeProps.offset}`]:
sizeProps.offset || sizeProps.offset === 0,
[`${prefixCls}-${size}-push-${sizeProps.push}`]: sizeProps.push || sizeProps.push === 0,
[`${prefixCls}-${size}-pull-${sizeProps.pull}`]: sizeProps.pull || sizeProps.pull === 0,
[`${prefixCls}-rtl`]: direction === 'rtl',
};
});
const classes = classNames(
prefixCls,
{
[`${prefixCls}-${span}`]: span !== undefined,
[`${prefixCls}-order-${order}`]: order,
[`${prefixCls}-offset-${offset}`]: offset,
[`${prefixCls}-push-${push}`]: push,
[`${prefixCls}-pull-${pull}`]: pull,
},
className,
sizeClassObj,
);
const prefixCls = getPrefixCls('col', customizePrefixCls);
return (
<RowContext.Consumer>
{({ gutter }) => {
let mergedStyle: React.CSSProperties = { ...style };
if (gutter) {
mergedStyle = {
...(gutter[0]! > 0
? {
paddingLeft: gutter[0]! / 2,
paddingRight: gutter[0]! / 2,
}
: {}),
...(gutter[1]! > 0
? {
paddingTop: gutter[1]! / 2,
paddingBottom: gutter[1]! / 2,
}
: {}),
...mergedStyle,
};
let sizeClassObj = {};
(['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] as const).forEach(size => {
let sizeProps: ColSize = {};
const propSize = props[size];
if (typeof propSize === 'number') {
sizeProps.span = propSize;
} else if (typeof propSize === 'object') {
sizeProps = propSize || {};
}
delete others[size];
sizeClassObj = {
...sizeClassObj,
[`${prefixCls}-${size}-${sizeProps.span}`]: sizeProps.span !== undefined,
[`${prefixCls}-${size}-order-${sizeProps.order}`]: sizeProps.order || sizeProps.order === 0,
[`${prefixCls}-${size}-offset-${sizeProps.offset}`]:
sizeProps.offset || sizeProps.offset === 0,
[`${prefixCls}-${size}-push-${sizeProps.push}`]: sizeProps.push || sizeProps.push === 0,
[`${prefixCls}-${size}-pull-${sizeProps.pull}`]: sizeProps.pull || sizeProps.pull === 0,
[`${prefixCls}-rtl`]: direction === 'rtl',
};
});
const classes = classNames(
prefixCls,
{
[`${prefixCls}-${span}`]: span !== undefined,
[`${prefixCls}-order-${order}`]: order,
[`${prefixCls}-offset-${offset}`]: offset,
[`${prefixCls}-push-${push}`]: push,
[`${prefixCls}-pull-${pull}`]: pull,
},
className,
sizeClassObj,
);
let mergedStyle: React.CSSProperties = { ...style };
if (gutter) {
mergedStyle = {
...(gutter[0]! > 0
? {
paddingLeft: gutter[0]! / 2,
paddingRight: gutter[0]! / 2,
}
if (flex) {
mergedStyle.flex = parseFlex(flex);
: {}),
...(gutter[1]! > 0
? {
paddingTop: gutter[1]! / 2,
paddingBottom: gutter[1]! / 2,
}
: {}),
...mergedStyle,
};
}
if (flex) {
mergedStyle.flex = parseFlex(flex);
}
return (
<div {...others} style={mergedStyle} className={classes} ref={ref}>
{children}
</div>
);
}}
</RowContext.Consumer>
);
};
return <ConfigConsumer>{renderCol}</ConfigConsumer>;
return (
<div {...others} style={mergedStyle} className={classes} ref={ref}>
{children}
</div>
);
});
Col.displayName = 'Col';

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import classNames from 'classnames';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import RowContext from './RowContext';
import { tuple } from '../_util/type';
import ResponsiveObserve, {
@ -21,6 +21,19 @@ export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
}
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
const {
prefixCls: customizePrefixCls,
justify,
align,
className,
style,
children,
gutter = 0,
...others
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const [screens, setScreens] = React.useState<ScreenMap>({
xs: true,
sm: true,
@ -29,8 +42,8 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
xl: true,
xxl: true,
});
const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>();
gutterRef.current = props.gutter;
const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>(gutter);
React.useEffect(() => {
const token = ResponsiveObserve.subscribe(screen => {
@ -43,14 +56,11 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
setScreens(screen);
}
});
return () => {
ResponsiveObserve.unsubscribe(token);
};
return () => ResponsiveObserve.unsubscribe(token);
}, []);
const getGutter = (): [number, number] => {
const results: [number, number] = [0, 0];
const { gutter = 0 } = props;
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
normalizedGutter.forEach((g, index) => {
if (typeof g === 'object') {
@ -68,55 +78,40 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
return results;
};
const renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
justify,
align,
className,
style,
children,
...others
} = props;
const prefixCls = getPrefixCls('row', customizePrefixCls);
const gutter = getGutter();
const classes = classNames(
prefixCls,
{
[`${prefixCls}-${justify}`]: justify,
[`${prefixCls}-${align}`]: align,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
);
const rowStyle = {
...(gutter[0]! > 0
? {
marginLeft: gutter[0]! / -2,
marginRight: gutter[0]! / -2,
}
: {}),
...(gutter[1]! > 0
? {
marginTop: gutter[1]! / -2,
marginBottom: gutter[1]! / 2,
}
: {}),
...style,
};
const otherProps = { ...others };
delete otherProps.gutter;
return (
<RowContext.Provider value={{ gutter }}>
<div {...otherProps} className={classes} style={rowStyle} ref={ref}>
{children}
</div>
</RowContext.Provider>
);
const prefixCls = getPrefixCls('row', customizePrefixCls);
const gutters = getGutter();
const classes = classNames(
prefixCls,
{
[`${prefixCls}-${justify}`]: justify,
[`${prefixCls}-${align}`]: align,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
);
const rowStyle = {
...(gutters[0]! > 0
? {
marginLeft: gutters[0]! / -2,
marginRight: gutters[0]! / -2,
}
: {}),
...(gutters[1]! > 0
? {
marginTop: gutters[1]! / -2,
marginBottom: gutters[1]! / 2,
}
: {}),
...style,
};
return <ConfigConsumer>{renderRow}</ConfigConsumer>;
return (
<RowContext.Provider value={{ gutter: gutters }}>
<div {...others} className={classes} style={rowStyle} ref={ref}>
{children}
</div>
</RowContext.Provider>
);
});
Row.displayName = 'Row';