diff --git a/packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js b/packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js
index ac1b16010647b..3d96eb1e8339a 100644
--- a/packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js
+++ b/packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js
@@ -32,12 +32,19 @@ export function checkControlledValueProps(
props.value == null
)
) {
- console.error(
- 'You provided a `value` prop to a form field without an ' +
- '`onChange` handler. This will render a read-only field. If ' +
- 'the field should be mutable use `defaultValue`. Otherwise, ' +
- 'set either `onChange` or `readOnly`.',
- );
+ if (tagName === 'select') {
+ console.error(
+ 'You provided a `value` prop to a form field without an ' +
+ '`onChange` handler. This will render a read-only field. If ' +
+ 'the field should be mutable use `defaultValue`. Otherwise, set `onChange`.',
+ );
+ } else {
+ console.error(
+ 'You provided a `value` prop to a form field without an ' +
+ '`onChange` handler. This will render a read-only field. If ' +
+ 'the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.',
+ );
+ }
}
if (
diff --git a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js
index 4332c52d124ec..9df6b07e23f65 100644
--- a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js
@@ -1289,5 +1289,122 @@ describe('ReactDOMSelect', () => {
' This value must be coerced to a string before using it here.',
);
});
+
+ it('should not warn about missing onChange if value is not set', () => {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+ ,
+ );
+ }).not.toThrow();
+ });
+
+ it('should not throw an error about missing onChange if value is undefined', () => {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+ ,
+ );
+ }).not.toThrow();
+ });
+
+ it('should not warn about missing onChange if onChange is set', () => {
+ const change = jest.fn();
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+ ,
+ );
+ }).not.toThrow();
+ });
+
+ it('should not warn about missing onChange if disabled is true', () => {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+ ,
+ );
+ }).not.toThrow();
+ });
+
+ it('should warn about missing onChange if value is false', () => {
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(
+ ,
+ ),
+ ).toErrorDev(
+ 'Warning: You provided a `value` prop to a form ' +
+ 'field without an `onChange` handler. This will render a read-only ' +
+ 'field. If the field should be mutable use `defaultValue`. ' +
+ 'Otherwise, set `onChange`.',
+ );
+ });
+
+ it('should warn about missing onChange if value is 0', () => {
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(
+ ,
+ ),
+ ).toErrorDev(
+ 'Warning: You provided a `value` prop to a form ' +
+ 'field without an `onChange` handler. This will render a read-only ' +
+ 'field. If the field should be mutable use `defaultValue`. ' +
+ 'Otherwise, set `onChange`.',
+ );
+ });
+
+ it('should warn about missing onChange if value is "0"', () => {
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(
+ ,
+ ),
+ ).toErrorDev(
+ 'Warning: You provided a `value` prop to a form ' +
+ 'field without an `onChange` handler. This will render a read-only ' +
+ 'field. If the field should be mutable use `defaultValue`. ' +
+ 'Otherwise, set `onChange`.',
+ );
+ });
+
+ it('should warn about missing onChange if value is ""', () => {
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(
+ ,
+ ),
+ ).toErrorDev(
+ 'Warning: You provided a `value` prop to a form ' +
+ 'field without an `onChange` handler. This will render a read-only ' +
+ 'field. If the field should be mutable use `defaultValue`. ' +
+ 'Otherwise, set `onChange`.',
+ );
+ });
});
});