diff --git a/packages/material-ui/src/Radio/Radio.js b/packages/material-ui/src/Radio/Radio.js
index 800d33dbde5a55..9fee569953d487 100644
--- a/packages/material-ui/src/Radio/Radio.js
+++ b/packages/material-ui/src/Radio/Radio.js
@@ -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. */
@@ -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);
diff --git a/packages/material-ui/src/RadioGroup/RadioGroup.test.js b/packages/material-ui/src/RadioGroup/RadioGroup.test.js
index e426f44575253a..76a73671ffd3d6 100644
--- a/packages/material-ui/src/RadioGroup/RadioGroup.test.js
+++ b/packages/material-ui/src/RadioGroup/RadioGroup.test.js
@@ -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('', () => {
let mount;
+ const render = createClientRender({ strict: true });
before(() => {
// StrictModeViolation: test uses #simulate
@@ -257,6 +260,61 @@ describe('', () => {
});
});
+ 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 (
+
+
+
+ );
+ });
+
+ describe('from props', () => {
+ it('should have the name prop from the instance', () => {
+ const radioGroupRef = React.createRef();
+ const { setProps } = render();
+
+ 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();
+
+ 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();
+
+ 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();
diff --git a/packages/material-ui/src/RadioGroup/index.d.ts b/packages/material-ui/src/RadioGroup/index.d.ts
index e7e280f415004c..b79185835ed329 100644
--- a/packages/material-ui/src/RadioGroup/index.d.ts
+++ b/packages/material-ui/src/RadioGroup/index.d.ts
@@ -1,2 +1,3 @@
export { default } from './RadioGroup';
export * from './RadioGroup';
+export { default as useRadioGroup, RadioGroupState } from './useRadioGroup';
diff --git a/packages/material-ui/src/RadioGroup/index.js b/packages/material-ui/src/RadioGroup/index.js
index 43f73d549d23b4..20284cadcf592c 100644
--- a/packages/material-ui/src/RadioGroup/index.js
+++ b/packages/material-ui/src/RadioGroup/index.js
@@ -1 +1,2 @@
export { default } from './RadioGroup';
+export { default as useRadioGroup } from './useRadioGroup';
diff --git a/packages/material-ui/src/RadioGroup/useRadioGroup.d.ts b/packages/material-ui/src/RadioGroup/useRadioGroup.d.ts
new file mode 100644
index 00000000000000..8277f3aca3b7b6
--- /dev/null
+++ b/packages/material-ui/src/RadioGroup/useRadioGroup.d.ts
@@ -0,0 +1,9 @@
+import { Context } from 'react';
+import { RadioGroupProps } from './RadioGroup';
+
+// shut off automatic exporting
+export {};
+
+export interface RadioGroupState extends Pick {}
+
+export default function useRadioGroup(): RadioGroupState;
diff --git a/packages/material-ui/src/RadioGroup/useRadioGroup.js b/packages/material-ui/src/RadioGroup/useRadioGroup.js
new file mode 100644
index 00000000000000..47b2186f39fe42
--- /dev/null
+++ b/packages/material-ui/src/RadioGroup/useRadioGroup.js
@@ -0,0 +1,6 @@
+import React from 'react';
+import RadioGroupContext from './RadioGroupContext';
+
+export default function useRadioGroup() {
+ return React.useContext(RadioGroupContext);
+}