refactor: use React.useContext() replace <ConfigConsumer /> (#39793)

* feat: use React.useContext() replace <ConfigConsumer />

* fix

* fix

* add
This commit is contained in:
lijianan 2022-12-25 18:34:42 +08:00 committed by GitHub
parent f488cb871b
commit 7f89d9a7c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 180 deletions

View File

@ -1,7 +1,7 @@
import classNames from 'classnames';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
import { ConfigContext } from '../config-provider';
import type { AntAnchor } from './Anchor';
import AnchorContext from './context';
@ -36,33 +36,31 @@ const AnchorLink: React.FC<AnchorLinkProps> = (props) => {
scrollTo?.(href);
};
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('anchor', customizePrefixCls);
const wrapperClassName = classNames(`${prefixCls}-link`, className, {
[`${prefixCls}-link-active`]: activeLink === href,
});
const titleClassName = classNames(`${prefixCls}-link-title`, {
[`${prefixCls}-link-title-active`]: activeLink === href,
});
return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const prefixCls = getPrefixCls('anchor', customizePrefixCls);
const active = activeLink === href;
const wrapperClassName = classNames(`${prefixCls}-link`, className, {
[`${prefixCls}-link-active`]: active,
});
const titleClassName = classNames(`${prefixCls}-link-title`, {
[`${prefixCls}-link-title-active`]: active,
});
return (
<div className={wrapperClassName}>
<a
className={titleClassName}
href={href}
title={typeof title === 'string' ? title : ''}
target={target}
onClick={handleClick}
>
{title}
</a>
{children}
</div>
);
}}
</ConfigConsumer>
<div className={wrapperClassName}>
<a
className={titleClassName}
href={href}
title={typeof title === 'string' ? title : ''}
target={target}
onClick={handleClick}
>
{title}
</a>
{children}
</div>
);
};

View File

@ -12,7 +12,7 @@ import toArray from 'rc-util/lib/Children/toArray';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
import { ConfigContext } from '../config-provider';
import type {
BaseOptionType,
DefaultOptionType,
@ -137,29 +137,25 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
);
}
return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const prefixCls = getPrefixCls('select', customizePrefixCls);
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
return (
<Select
ref={ref}
{...omit(props, ['dataSource', 'dropdownClassName'])}
prefixCls={prefixCls}
popupClassName={popupClassName || dropdownClassName}
className={classNames(`${prefixCls}-auto-complete`, className)}
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as any}
{...{
// Internal api
getInputElement,
}}
>
{optionChildren}
</Select>
);
const prefixCls = getPrefixCls('select', customizePrefixCls);
return (
<Select
ref={ref}
{...omit(props, ['dataSource', 'dropdownClassName'])}
prefixCls={prefixCls}
popupClassName={popupClassName || dropdownClassName}
className={classNames(`${prefixCls}-auto-complete`, className)}
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as any}
{...{
// Internal api
getInputElement,
}}
</ConfigConsumer>
>
{optionChildren}
</Select>
);
};

View File

@ -1,7 +1,7 @@
import classNames from 'classnames';
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
export interface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {
prefixCls?: string;
@ -10,17 +10,13 @@ export interface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {
style?: React.CSSProperties;
}
const Grid: React.FC<CardGridProps> = ({ prefixCls, className, hoverable = true, ...props }) => (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const prefix = getPrefixCls('card', prefixCls);
const classString = classNames(`${prefix}-grid`, className, {
[`${prefix}-grid-hoverable`]: hoverable,
});
return <div {...props} className={classString} />;
}}
</ConfigConsumer>
);
const Grid: React.FC<CardGridProps> = ({ prefixCls, className, hoverable = true, ...props }) => {
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefix = getPrefixCls('card', prefixCls);
const classString = classNames(`${prefix}-grid`, className, {
[`${prefix}-grid-hoverable`]: hoverable,
});
return <div {...props} className={classString} />;
};
export default Grid;

View File

@ -1,7 +1,7 @@
import classNames from 'classnames';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
import { ConfigContext } from '../config-provider';
export interface CardMetaProps {
prefixCls?: string;
@ -12,39 +12,41 @@ export interface CardMetaProps {
description?: React.ReactNode;
}
const Meta: React.FC<CardMetaProps> = (props) => (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
className,
avatar,
title,
description,
...others
} = props;
const prefixCls = getPrefixCls('card', customizePrefixCls);
const classString = classNames(`${prefixCls}-meta`, className);
const avatarDom = avatar ? <div className={`${prefixCls}-meta-avatar`}>{avatar}</div> : null;
const titleDom = title ? <div className={`${prefixCls}-meta-title`}>{title}</div> : null;
const descriptionDom = description ? (
<div className={`${prefixCls}-meta-description`}>{description}</div>
) : null;
const MetaDetail =
titleDom || descriptionDom ? (
<div className={`${prefixCls}-meta-detail`}>
{titleDom}
{descriptionDom}
</div>
) : null;
return (
<div {...others} className={classString}>
{avatarDom}
{MetaDetail}
</div>
);
}}
</ConfigConsumer>
);
const Meta: React.FC<CardMetaProps> = (props) => {
const { prefixCls: customizePrefixCls, className, avatar, title, description, ...others } = props;
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('card', customizePrefixCls);
const classString = classNames(`${prefixCls}-meta`, className);
const avatarDom: React.ReactNode = avatar ? (
<div className={`${prefixCls}-meta-avatar`}>{avatar}</div>
) : null;
const titleDom: React.ReactNode = title ? (
<div className={`${prefixCls}-meta-title`}>{title}</div>
) : null;
const descriptionDom: React.ReactNode = description ? (
<div className={`${prefixCls}-meta-description`}>{description}</div>
) : null;
const MetaDetail: React.ReactNode =
titleDom || descriptionDom ? (
<div className={`${prefixCls}-meta-detail`}>
{titleDom}
{descriptionDom}
</div>
) : null;
return (
<div {...others} className={classString}>
{avatarDom}
{MetaDetail}
</div>
);
};
export default Meta;

View File

@ -102,17 +102,14 @@ export function withConfigConsumer<ExportProps extends BasicExportProps>(config:
Component: React.ComponentType<ExportProps>,
): React.FC<ExportProps> & ComponentDef {
// Wrap with ConfigConsumer. Since we need compatible with react 15, be careful when using ref methods
const SFC = ((props: ExportProps) => (
<ConfigConsumer>
{(configProps: ConfigConsumerProps) => {
const { prefixCls: basicPrefixCls } = config;
const { getPrefixCls } = configProps;
const { prefixCls: customizePrefixCls } = props;
const prefixCls = getPrefixCls(basicPrefixCls, customizePrefixCls);
return <Component {...configProps} {...props} prefixCls={prefixCls} />;
}}
</ConfigConsumer>
)) as React.FC<ExportProps> & ComponentDef;
const SFC: React.FC<ExportProps> & ComponentDef = ((props) => {
const configProps = React.useContext<ConfigConsumerProps>(ConfigContext);
const { getPrefixCls } = configProps;
const { prefixCls: basicPrefixCls } = config;
const { prefixCls: customizePrefixCls } = props;
const prefixCls = getPrefixCls(basicPrefixCls, customizePrefixCls);
return <Component {...configProps} {...props} prefixCls={prefixCls} />;
}) as React.FC<ExportProps> & ComponentDef;
const cons: ConstructorProps = Component.constructor as ConstructorProps;
const name = (cons && cons.displayName) || Component.name || 'Component';

View File

@ -6,7 +6,7 @@ import { composeRef } from 'rc-util/lib/ref';
import * as React from 'react';
import { useRef, useState } from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
import { ConfigContext } from '../config-provider';
import useRemovePasswordTimeout from './hooks/useRemovePasswordTimeout';
import type { InputProps, InputRef } from './Input';
import Input from './Input';
@ -88,39 +88,37 @@ const Password = React.forwardRef<InputRef, PasswordProps>((props, ref) => {
return React.cloneElement(React.isValidElement(icon) ? icon : <span>{icon}</span>, iconProps);
};
const renderPassword = ({ getPrefixCls }: ConfigConsumerProps) => {
const {
className,
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
size,
...restProps
} = props;
const {
className,
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
size,
...restProps
} = props;
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
const prefixCls = getPrefixCls('input-password', customizePrefixCls);
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
const prefixCls = getPrefixCls('input-password', customizePrefixCls);
const suffixIcon = visibilityToggle && getIcon(prefixCls);
const inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-${size}`]: !!size,
});
const suffixIcon = visibilityToggle && getIcon(prefixCls);
const omittedProps: InputProps = {
...omit(restProps, ['suffix', 'iconRender', 'visibilityToggle']),
type: visible ? 'text' : 'password',
className: inputClassName,
prefixCls: inputPrefixCls,
suffix: suffixIcon,
};
const inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-${size}`]: !!size,
});
if (size) {
omittedProps.size = size;
}
return <Input ref={composeRef(ref, inputRef)} {...omittedProps} />;
const omittedProps: InputProps = {
...omit(restProps, ['suffix', 'iconRender', 'visibilityToggle']),
type: visible ? 'text' : 'password',
className: inputClassName,
prefixCls: inputPrefixCls,
suffix: suffixIcon,
};
return <ConfigConsumer>{renderPassword}</ConfigConsumer>;
if (size) {
omittedProps.size = size;
}
return <Input ref={composeRef(ref, inputRef)} {...omittedProps} />;
});
if (process.env.NODE_ENV !== 'production') {

View File

@ -3,7 +3,7 @@ import { debounce } from 'throttle-debounce';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer, ConfigContext } from '../config-provider';
import { ConfigContext } from '../config-provider';
import { cloneElement, isValidElement } from '../_util/reactNode';
import useStyle from './style/index';
@ -100,57 +100,57 @@ const Spin: React.FC<SpinClassProps> = (props) => {
};
}, [delay, customSpinning]);
const isNestedPattern = () => typeof children !== 'undefined';
const isNestedPattern = React.useMemo<boolean>(() => typeof children !== 'undefined', [children]);
const renderSpin = ({ direction }: ConfigConsumerProps) => {
const spinClassName = classNames(
prefixCls,
{
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-spinning`]: spinning,
[`${prefixCls}-show-text`]: !!tip,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
hashId,
);
const { direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
// fix https://fb.me/react-unknown-prop
const divProps = omit(restProps, ['indicator', 'prefixCls']);
const spinClassName = classNames(
prefixCls,
{
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-spinning`]: spinning,
[`${prefixCls}-show-text`]: !!tip,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
hashId,
);
const spinElement = (
const containerClassName = classNames(`${prefixCls}-container`, {
[`${prefixCls}-blur`]: spinning,
});
// fix https://fb.me/react-unknown-prop
const divProps = omit(restProps, ['indicator', 'prefixCls']);
const spinElement: React.ReactNode = (
<div
{...divProps}
style={style}
className={spinClassName}
aria-live="polite"
aria-busy={spinning}
>
{renderIndicator(prefixCls, props)}
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
</div>
);
if (isNestedPattern) {
return (
<div
{...divProps}
style={style}
className={spinClassName}
aria-live="polite"
aria-busy={spinning}
className={classNames(`${prefixCls}-nested-loading`, wrapperClassName, hashId)}
>
{renderIndicator(prefixCls, props)}
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
{spinning && <div key="loading">{spinElement}</div>}
<div className={containerClassName} key="container">
{children}
</div>
</div>
);
if (isNestedPattern()) {
const containerClassName = classNames(`${prefixCls}-container`, {
[`${prefixCls}-blur`]: spinning,
});
return (
<div
{...divProps}
className={classNames(`${prefixCls}-nested-loading`, wrapperClassName, hashId)}
>
{spinning && <div key="loading">{spinElement}</div>}
<div className={containerClassName} key="container">
{children}
</div>
</div>
);
}
return spinElement;
};
return <ConfigConsumer>{renderSpin}</ConfigConsumer>;
}
return spinElement;
};
const SpinFC: SpinFCType = (props) => {