From 43f93a50b48feaf0ae8798613e06c514630ad224 Mon Sep 17 00:00:00 2001 From: Rui Botto Date: Thu, 20 Dec 2018 19:52:19 +0100 Subject: [PATCH] [RadioGroup] Support uncontrolled mode (#13929) * [RadioGroup] Support uncontrolled mode * Add unit test * Integrate PR's feedback --- .../material-ui/src/RadioGroup/RadioGroup.js | 24 +++++++++++--- .../src/RadioGroup/RadioGroup.test.js | 33 +++++++++++-------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/packages/material-ui/src/RadioGroup/RadioGroup.js b/packages/material-ui/src/RadioGroup/RadioGroup.js index 02f139ac9a2aac..47a53c94f5c615 100644 --- a/packages/material-ui/src/RadioGroup/RadioGroup.js +++ b/packages/material-ui/src/RadioGroup/RadioGroup.js @@ -9,6 +9,15 @@ import { createChainedFunction, find } from '../utils/helpers'; class RadioGroup extends React.Component { radios = []; + state = { + value: null, + }; + + constructor(props) { + super(); + this.isControlled = props.value != null; + } + focus = () => { if (!this.radios || !this.radios.length) { return; @@ -30,15 +39,22 @@ class RadioGroup extends React.Component { focusRadios[0].focus(); }; - handleRadioChange = (event, checked) => { - if (checked && this.props.onChange) { + handleChange = event => { + if (!this.isControlled) { + this.setState({ + value: event.target.value, + }); + } + + if (this.props.onChange) { this.props.onChange(event, event.target.value); } }; render() { - const { children, name, value, onChange, ...other } = this.props; + const { children, name, value: valueProp, onChange, ...other } = this.props; + const value = this.isControlled ? valueProp : this.state.value; this.radios = []; return ( @@ -64,7 +80,7 @@ class RadioGroup extends React.Component { } }, checked: value === child.props.value, - onChange: createChainedFunction(child.props.onChange, this.handleRadioChange), + onChange: createChainedFunction(child.props.onChange, this.handleChange), }); })} diff --git a/packages/material-ui/src/RadioGroup/RadioGroup.test.js b/packages/material-ui/src/RadioGroup/RadioGroup.test.js index 450862fddef2e8..4924aeb4f3fe39 100644 --- a/packages/material-ui/src/RadioGroup/RadioGroup.test.js +++ b/packages/material-ui/src/RadioGroup/RadioGroup.test.js @@ -37,6 +37,25 @@ describe('', () => { assert.strictEqual(handleKeyDown.args[0][0], event); }); + it('should support uncontrolled mode', () => { + const wrapper = shallow( + + + , + ); + + const radio = wrapper.children().first(); + const event = { target: { value: 'one' } }; + radio.simulate('change', event, true); + assert.strictEqual( + wrapper + .children() + .first() + .props().checked, + true, + ); + }); + describe('imperative focus()', () => { let wrapper; @@ -134,20 +153,6 @@ describe('', () => { assert.strictEqual(handleChange.calledWith(event), true); }); - it('should not fire onChange if not checked', () => { - const handleChange = spy(); - const wrapper = shallow( - - - - , - ); - - const internalRadio = wrapper.children().first(); - internalRadio.simulate('change', { target: { value: 'woofRadioGroup' } }, false); - assert.strictEqual(handleChange.callCount, 0); - }); - it('should chain the onChange property', () => { const handleChange1 = spy(); const handleChange2 = spy();