Skip to content

Commit

Permalink
[RadioGroup] Add useRadioGroup Hook (#18920)
Browse files Browse the repository at this point in the history
  • Loading branch information
NMinhNguyen authored and eps1lon committed Dec 27, 2019
1 parent 3afb41f commit 219876b
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 3 deletions.
4 changes: 2 additions & 2 deletions packages/material-ui/src/Radio/Radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { fade } from '../styles/colorManipulator';
import capitalize from '../utils/capitalize';
import createChainedFunction from '../utils/createChainedFunction';
import withStyles from '../styles/withStyles';
import RadioGroupContext from '../RadioGroup/RadioGroupContext';
import useRadioGroup from '../RadioGroup/useRadioGroup';

export const styles = theme => ({
/* Styles applied to the root element. */
Expand Down Expand Up @@ -67,7 +67,7 @@ const Radio = React.forwardRef(function Radio(props, ref) {
size = 'medium',
...other
} = props;
const radioGroup = React.useContext(RadioGroupContext);
const radioGroup = useRadioGroup();

let checked = checkedProp;
const onChange = createChainedFunction(onChangeProp, radioGroup && radioGroup.onChange);
Expand Down
60 changes: 59 additions & 1 deletion packages/material-ui/src/RadioGroup/RadioGroup.test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { spy } from 'sinon';
import * as PropTypes from 'prop-types';
import { createMount, findOutermostIntrinsic } from '@material-ui/core/test-utils';
import describeConformance from '../test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import FormGroup from '../FormGroup';
import Radio from '../Radio';
import RadioGroup from './RadioGroup';
import consoleErrorMock from 'test/utils/consoleErrorMock';
import useRadioGroup from './useRadioGroup';

describe('<RadioGroup />', () => {
let mount;
const render = createClientRender({ strict: true });

before(() => {
// StrictModeViolation: test uses #simulate
Expand Down Expand Up @@ -257,6 +260,61 @@ describe('<RadioGroup />', () => {
});
});

describe('useRadioGroup', () => {
const RadioGroupController = React.forwardRef((_, ref) => {
const radioGroup = useRadioGroup();
React.useImperativeHandle(ref, () => radioGroup, [radioGroup]);
return null;
});

const RadioGroupControlled = React.forwardRef(function RadioGroupControlled(props, ref) {
return (
<RadioGroup {...props}>
<RadioGroupController ref={ref} />
</RadioGroup>
);
});

describe('from props', () => {
it('should have the name prop from the instance', () => {
const radioGroupRef = React.createRef();
const { setProps } = render(<RadioGroupControlled name="group" ref={radioGroupRef} />);

expect(radioGroupRef.current).to.have.property('name', 'group');

setProps({ name: 'anotherGroup' });
expect(radioGroupRef.current).to.have.property('name', 'anotherGroup');
});

it('should have the value prop from the instance', () => {
const radioGroupRef = React.createRef();
const { setProps } = render(<RadioGroupControlled ref={radioGroupRef} value="" />);

expect(radioGroupRef.current).to.have.property('value', '');

setProps({ value: 'one' });
expect(radioGroupRef.current).to.have.property('value', 'one');
});
});

describe('callbacks', () => {
describe('onChange', () => {
it('should set the value state', () => {
const radioGroupRef = React.createRef();
render(<RadioGroupControlled ref={radioGroupRef} defaultValue="zero" />);

expect(radioGroupRef.current).to.have.property('value', 'zero');

radioGroupRef.current.onChange({ target: { value: 'one' } });
expect(radioGroupRef.current).to.have.property('value', 'one');

radioGroupRef.current.onChange({ target: { value: 'two' } });
expect(radioGroupRef.current).to.have.property('value', 'two');
});
});
});
});

describe('warnings', () => {
beforeEach(() => {
consoleErrorMock.spy();
Expand Down
1 change: 1 addition & 0 deletions packages/material-ui/src/RadioGroup/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default } from './RadioGroup';
export * from './RadioGroup';
export { default as useRadioGroup, RadioGroupState } from './useRadioGroup';
1 change: 1 addition & 0 deletions packages/material-ui/src/RadioGroup/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from './RadioGroup';
export { default as useRadioGroup } from './useRadioGroup';
9 changes: 9 additions & 0 deletions packages/material-ui/src/RadioGroup/useRadioGroup.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Context } from 'react';
import { RadioGroupProps } from './RadioGroup';

// shut off automatic exporting
export {};

export interface RadioGroupState extends Pick<RadioGroupProps, 'name' | 'onChange' | 'value'> {}

export default function useRadioGroup(): RadioGroupState;
6 changes: 6 additions & 0 deletions packages/material-ui/src/RadioGroup/useRadioGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
import RadioGroupContext from './RadioGroupContext';

export default function useRadioGroup() {
return React.useContext(RadioGroupContext);
}

0 comments on commit 219876b

Please sign in to comment.