diff --git a/components/radio/__tests__/group.test.js b/components/radio/__tests__/group.test.js index ace814c4d091..5aa9adad828c 100644 --- a/components/radio/__tests__/group.test.js +++ b/components/radio/__tests__/group.test.js @@ -170,10 +170,35 @@ describe('Radio Group', () => { }); it('passes prefixCls down to radio', () => { - const options = [{ label: 'Apple', value: 'Apple' }, { label: 'Orange', value: 'Orange', style: { fontSize: 12 } }]; + const options = [ + { label: 'Apple', value: 'Apple' }, + { label: 'Orange', value: 'Orange', style: { fontSize: 12 } }, + ]; const wrapper = render(); expect(wrapper).toMatchSnapshot(); }); + + describe('value is null or undefined', () => { + it('use `defaultValue` when `value` is undefined', () => { + const options = [{ label: 'Bamboo', value: 'bamboo' }]; + const wrapper = mount( + , + ); + + expect(wrapper.state().value).toEqual('bamboo'); + }); + + [undefined, null].forEach(newValue => { + it(`should set value back when value change back to ${newValue}`, () => { + const options = [{ label: 'Bamboo', value: 'bamboo' }]; + const wrapper = mount(); + expect(wrapper.state().value).toEqual('bamboo'); + + wrapper.setProps({ value: newValue }); + expect(wrapper.state().value).toEqual(newValue); + }); + }); + }); }); diff --git a/components/radio/group.tsx b/components/radio/group.tsx index aec896ab798f..3eca00110013 100644 --- a/components/radio/group.tsx +++ b/components/radio/group.tsx @@ -28,28 +28,29 @@ class RadioGroup extends React.PureComponent { buttonStyle: 'outline' as RadioGroupButtonStyle, }; - static getDerivedStateFromProps(nextProps: RadioGroupProps) { - if ('value' in nextProps) { - return { - value: nextProps.value, - }; - } - const checkedValue = getCheckedValue(nextProps.children); - if (checkedValue) { - return { - value: checkedValue.value, - }; + static getDerivedStateFromProps(nextProps: RadioGroupProps, prevState: RadioGroupState) { + const newState: Partial = { + prevPropValue: nextProps.value, + }; + + if (nextProps.value !== undefined || prevState.prevPropValue !== nextProps.value) { + newState.value = nextProps.value; + } else { + const checkedValue = getCheckedValue(nextProps.children); + if (checkedValue) { + newState.value = checkedValue.value; + } } - return null; + return newState; } constructor(props: RadioGroupProps) { super(props); let value; - if ('value' in props) { + if (props.value !== undefined) { value = props.value; - } else if ('defaultValue' in props) { + } else if (props.defaultValue !== undefined) { value = props.defaultValue; } else { const checkedValue = getCheckedValue(props.children); @@ -57,6 +58,7 @@ class RadioGroup extends React.PureComponent { } this.state = { value, + prevPropValue: props.value, }; } diff --git a/components/radio/interface.tsx b/components/radio/interface.tsx index 528f82820f79..8767046b9b55 100644 --- a/components/radio/interface.tsx +++ b/components/radio/interface.tsx @@ -20,6 +20,7 @@ export interface RadioGroupProps extends AbstractCheckboxGroupProps { export interface RadioGroupState { value: any; + prevPropValue: any; } export interface RadioGroupContextProps {