diff --git a/components/checkbox/Checkbox.tsx b/components/checkbox/Checkbox.tsx index 4e8c0db79ea2..5a37868a22d8 100644 --- a/components/checkbox/Checkbox.tsx +++ b/components/checkbox/Checkbox.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; +import { polyfill } from 'react-lifecycles-compat'; import classNames from 'classnames'; import RcCheckbox from 'rc-checkbox'; import shallowEqual from 'shallowequal'; @@ -40,7 +41,7 @@ export interface CheckboxChangeEvent { nativeEvent: MouseEvent; } -export default class Checkbox extends React.Component { +class Checkbox extends React.Component { static Group: typeof CheckboxGroup; static defaultProps = { indeterminate: false, @@ -54,6 +55,31 @@ export default class Checkbox extends React.Component { private rcCheckbox: any; + componentDidMount() { + const { value } = this.props; + const { checkboxGroup = {} } = this.context || {}; + if (checkboxGroup.registerValue) { + checkboxGroup.registerValue(value); + } + } + + componentDidUpdate({ value: prevValue }: CheckboxProps) { + const { value } = this.props; + const { checkboxGroup = {} } = this.context || {}; + if (value !== prevValue && checkboxGroup.registerValue && checkboxGroup.cancelValue) { + checkboxGroup.cancelValue(prevValue); + checkboxGroup.registerValue(value); + } + } + + componentWillUnmount() { + const { value } = this.props; + const { checkboxGroup = {} } = this.context || {}; + if (checkboxGroup.cancelValue) { + checkboxGroup.cancelValue(value); + } + } + shouldComponentUpdate( nextProps: CheckboxProps, nextState: {}, @@ -134,3 +160,7 @@ export default class Checkbox extends React.Component { return {this.renderCheckbox}; } } + +polyfill(Checkbox); + +export default Checkbox; diff --git a/components/checkbox/Group.tsx b/components/checkbox/Group.tsx index d666680419b7..24ecfa7e45fd 100644 --- a/components/checkbox/Group.tsx +++ b/components/checkbox/Group.tsx @@ -32,7 +32,8 @@ export interface CheckboxGroupProps extends AbstractCheckboxGroupProps { } export interface CheckboxGroupState { - value: any; + value: CheckboxValueType[]; + registeredValues: CheckboxValueType[]; } export interface CheckboxGroupContext { @@ -72,6 +73,7 @@ class CheckboxGroup extends React.Component { + this.setState(({ registeredValues }) => ({ + registeredValues: [...registeredValues, value], + })); + }; + + cancelValue = (value: string) => { + this.setState(({ registeredValues }) => ({ + registeredValues: registeredValues.filter(val => val !== value), + })); + }; + getOptions() { const { options } = this.props; // https://github.com/Microsoft/TypeScript/issues/7960 @@ -105,6 +123,7 @@ class CheckboxGroup extends React.Component { + const { registeredValues } = this.state; const optionIndex = this.state.value.indexOf(option.value); const value = [...this.state.value]; if (optionIndex === -1) { @@ -117,7 +136,7 @@ class CheckboxGroup extends React.Component registeredValues.indexOf(val) !== -1)); } }; diff --git a/components/checkbox/__tests__/group.test.js b/components/checkbox/__tests__/group.test.js index 4b264323b91b..c3cf158ff7dc 100644 --- a/components/checkbox/__tests__/group.test.js +++ b/components/checkbox/__tests__/group.test.js @@ -111,4 +111,26 @@ describe('CheckboxGroup', () => { expect(onChange).toHaveBeenCalled(); expect(onChange.mock.calls[0][0].target.value).toEqual('my'); }); + + // https://github.com/ant-design/ant-design/issues/16376 + it('onChange should filter removed value', () => { + const onChange = jest.fn(); + const wrapper = mount( + + + + , + ); + + wrapper.setProps({ + children: [], + }); + + wrapper + .find('.ant-checkbox-input') + .at(0) + .simulate('change'); + + expect(onChange).toHaveBeenCalledWith([2]); + }); });