chore: replace legacy context and use PureComponent (#21597)

This commit is contained in:
zefeng 2020-02-26 16:09:22 +08:00 committed by GitHub
parent 0f5dc22966
commit e3fbb0dbd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 71 deletions

View File

@ -0,0 +1,8 @@
import * as React from 'react';
import { RadioGroupContextProps } from './interface';
const RadioGroupContext = React.createContext<RadioGroupContextProps | null>(null);
export const RadioGroupContextProvider = RadioGroupContext.Provider;
export default RadioGroupContext;

View File

@ -1,5 +1,4 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import Radio from './radio';
import {
@ -10,6 +9,7 @@ import {
} from './interface';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import SizeContext from '../config-provider/SizeContext';
import { RadioGroupContextProvider } from './context';
function getCheckedValue(children: React.ReactNode) {
let value = null;
@ -28,10 +28,6 @@ class RadioGroup extends React.PureComponent<RadioGroupProps, RadioGroupState> {
buttonStyle: 'outline' as RadioGroupButtonStyle,
};
static childContextTypes = {
radioGroup: PropTypes.any,
};
static getDerivedStateFromProps(nextProps: RadioGroupProps) {
if ('value' in nextProps) {
return {
@ -64,17 +60,6 @@ class RadioGroup extends React.PureComponent<RadioGroupProps, RadioGroupState> {
};
}
getChildContext() {
return {
radioGroup: {
onChange: this.onRadioChange,
value: this.state.value,
disabled: this.props.disabled,
name: this.props.name,
},
};
}
onRadioChange = (ev: RadioChangeEvent) => {
const lastValue = this.state.value;
const { value } = ev.target;
@ -167,7 +152,18 @@ class RadioGroup extends React.PureComponent<RadioGroupProps, RadioGroupState> {
};
render() {
return <ConfigConsumer>{this.renderGroup}</ConfigConsumer>;
return (
<RadioGroupContextProvider
value={{
onChange: this.onRadioChange,
value: this.state.value,
disabled: this.props.disabled,
name: this.props.name,
}}
>
<ConfigConsumer>{this.renderGroup}</ConfigConsumer>
</RadioGroupContextProvider>
);
}
}

View File

@ -13,7 +13,7 @@ Radio.
## API
### Radio
### Radio/Radio.Button
| Property | Description | Type | Default |
| --- | --- | --- | --- |

View File

@ -14,13 +14,14 @@ title: Radio
## API
### Radio
### Radio/Radio.Button
| 参数 | 说明 | 类型 | 默认值 |
| -------------- | --------------------------------- | ------- | ------ |
| autoFocus | 自动获取焦点 | boolean | false |
| checked | 指定当前是否选中 | boolean | false |
| defaultChecked | 初始是否选中 | boolean | false |
| disabled | 禁用 Radio | boolean | false |
| value | 根据 value 进行比较,判断是否选中 | any | |
### RadioGroup

View File

@ -22,13 +22,11 @@ export interface RadioGroupState {
value: any;
}
export interface RadioGroupContext {
radioGroup: {
onChange: React.ChangeEventHandler<HTMLInputElement>;
value: any;
disabled: boolean;
name: string;
};
export interface RadioGroupContextProps {
onChange: (e: RadioChangeEvent) => void;
value: any;
disabled?: boolean;
name?: string;
}
export type RadioProps = AbstractCheckboxProps<RadioChangeEvent>;

View File

@ -1,14 +1,13 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import RcCheckbox from 'rc-checkbox';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import RadioGroup from './group';
import RadioButton from './radioButton';
import { RadioProps, RadioChangeEvent, RadioGroupContext } from './interface';
import { RadioProps, RadioChangeEvent } from './interface';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import RadioGroupContext from './context';
export default class Radio extends React.Component<RadioProps, {}> {
export default class Radio extends React.PureComponent<RadioProps, {}> {
static Group: typeof RadioGroup;
static Button: typeof RadioButton;
@ -17,22 +16,10 @@ export default class Radio extends React.Component<RadioProps, {}> {
type: 'radio',
};
static contextTypes = {
radioGroup: PropTypes.any,
};
context: any;
static contextType = RadioGroupContext;
private rcCheckbox: any;
shouldComponentUpdate(nextProps: RadioProps, nextState: {}, nextContext: RadioGroupContext) {
return (
!shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState) ||
!shallowEqual(this.context.radioGroup, nextContext.radioGroup)
);
}
saveCheckbox = (node: any) => {
this.rcCheckbox = node;
};
@ -42,8 +29,8 @@ export default class Radio extends React.Component<RadioProps, {}> {
this.props.onChange(e);
}
if (this.context.radioGroup && this.context.radioGroup.onChange) {
this.context.radioGroup.onChange(e);
if (this.context?.onChange) {
this.context.onChange(e);
}
};
@ -58,14 +45,13 @@ export default class Radio extends React.Component<RadioProps, {}> {
renderRadio = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const { props, context } = this;
const { prefixCls: customizePrefixCls, className, children, style, ...restProps } = props;
const { radioGroup } = context;
const prefixCls = getPrefixCls('radio', customizePrefixCls);
const radioProps: RadioProps = { ...restProps };
if (radioGroup) {
radioProps.name = radioGroup.name;
if (context) {
radioProps.name = context.name;
radioProps.onChange = this.onChange;
radioProps.checked = props.value === radioGroup.value;
radioProps.disabled = props.disabled || radioGroup.disabled;
radioProps.checked = props.value === context.value;
radioProps.disabled = props.disabled || context.disabled;
}
const wrapperClassString = classNames(className, {
[`${prefixCls}-wrapper`]: true,

View File

@ -1,31 +1,28 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import Radio from './radio';
import { RadioChangeEvent } from './interface';
import { AbstractCheckboxProps } from '../checkbox/Checkbox';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import RadioGroupContext from './context';
export type RadioButtonProps = AbstractCheckboxProps<RadioChangeEvent>;
export default class RadioButton extends React.Component<RadioButtonProps, any> {
static contextTypes = {
radioGroup: PropTypes.any,
};
const RadioButton = (props: RadioButtonProps) => {
const radioGroupContext = React.useContext(RadioGroupContext);
context: any;
return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, ...radioProps }: RadioButtonProps = props;
const prefixCls = getPrefixCls('radio-button', customizePrefixCls);
if (radioGroupContext) {
radioProps.checked = props.value === radioGroupContext.value;
radioProps.disabled = props.disabled || radioGroupContext.disabled;
}
return <Radio prefixCls={prefixCls} {...radioProps} />;
}}
</ConfigConsumer>
);
};
renderRadioButton = ({ getPrefixCls }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, ...radioProps }: RadioButtonProps = this.props;
const prefixCls = getPrefixCls('radio-button', customizePrefixCls);
if (this.context.radioGroup) {
radioProps.checked = this.props.value === this.context.radioGroup.value;
radioProps.disabled = this.props.disabled || this.context.radioGroup.disabled;
}
return <Radio prefixCls={prefixCls} {...radioProps} />;
};
render() {
return <ConfigConsumer>{this.renderRadioButton}</ConfigConsumer>;
}
}
export default RadioButton;