Skip to content

Commit

Permalink
refactor: use React.useContext() replace <ConfigConsumer /> (#39793)
Browse files Browse the repository at this point in the history
* feat: use React.useContext() replace <ConfigConsumer />

* fix

* fix

* add
  • Loading branch information
li-jia-nan committed Dec 25, 2022
1 parent f488cb8 commit 7f89d9a
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 185 deletions.
52 changes: 25 additions & 27 deletions components/anchor/AnchorLink.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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>
);
};

Expand Down
40 changes: 18 additions & 22 deletions components/auto-complete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -137,29 +137,25 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
);
}

const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);

const prefixCls = getPrefixCls('select', customizePrefixCls);

return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
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,
}}
>
{optionChildren}
</Select>
);
<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>
);
};

Expand Down
22 changes: 9 additions & 13 deletions components/card/Grid.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
72 changes: 37 additions & 35 deletions components/card/Meta.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
19 changes: 8 additions & 11 deletions components/config-provider/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
62 changes: 30 additions & 32 deletions components/input/Password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
const prefixCls = getPrefixCls('input-password', customizePrefixCls);

const suffixIcon = visibilityToggle && getIcon(prefixCls);
const inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-${size}`]: !!size,
});

const omittedProps: InputProps = {
...omit(restProps, ['suffix', 'iconRender', 'visibilityToggle']),
type: visible ? 'text' : 'password',
className: inputClassName,
prefixCls: inputPrefixCls,
suffix: suffixIcon,
};

if (size) {
omittedProps.size = size;
}

return <Input ref={composeRef(ref, inputRef)} {...omittedProps} />;
const {
className,
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
size,
...restProps
} = props;

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 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') {
Expand Down

0 comments on commit 7f89d9a

Please sign in to comment.