From e350c1f91af8cb99b2b460e2cf71600ed864e22f Mon Sep 17 00:00:00 2001 From: hypnos Date: Mon, 24 Apr 2017 16:14:33 +0300 Subject: [PATCH 1/2] Warn if a falsy `value` or `checked` prop is provided without an `onChange` handler or an explicit `readOnly` flag --- scripts/fiber/tests-passing.txt | 3 + .../utils/ReactControlledValuePropTypes.js | 4 +- .../wrappers/__tests__/ReactDOMInput-test.js | 61 ++++++++++++++++++- .../__tests__/ReactDOMTextarea-test.js | 2 +- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index decc4bd5b943..a6e427af22fe 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -1478,6 +1478,9 @@ src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js * should control radio buttons * should control radio buttons if the tree updates during render * should warn with value and no onChange handler and readOnly specified +* should warn with an empty value and no onChange handler and readOnly specified +* should warn with a value of number `0` and no onChange handler and readOnly specified +* should warn with a value of `false` and no onChange handler and readOnly specified * should have a this value of undefined if bind is not used * should warn with checked and no onChange handler with readOnly specified * should update defaultValue to empty string diff --git a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js index 0f64cd58c5a2..a8dcdd362929 100644 --- a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js +++ b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js @@ -29,7 +29,7 @@ var hasReadOnlyValue = { var propTypes = { value: function(props, propName, componentName) { if ( - !props[propName] || + props[propName] == null || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || @@ -46,7 +46,7 @@ var propTypes = { }, checked: function(props, propName, componentName) { if ( - !props[propName] || + props[propName] == null || props.onChange || props.readOnly || props.disabled diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js index 16b2fba74814..08293e2b7eb8 100644 --- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js +++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js @@ -651,6 +651,63 @@ describe('ReactDOMInput', () => { ); }); + it('should warn with an empty value and no onChange handler and readOnly specified', () => { + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(0); + + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(1); + expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( + 'Warning: Failed form propType: 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`.\n' + + ' in input (at **)', + ); + }); + + it('should warn with a value of number `0` and no onChange handler and readOnly specified', () => { + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(0); + + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(1); + expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( + 'Warning: Failed form propType: 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`.\n' + + ' in input (at **)', + ); + }); + + it('should warn with a value of `false` and no onChange handler and readOnly specified', () => { + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(0); + + ReactTestUtils.renderIntoDocument( + , + ); + expectDev(console.error.calls.count()).toBe(1); + expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( + 'Warning: Failed form propType: 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`.\n' + + ' in input (at **)', + ); + }); + it('should have a this value of undefined if bind is not used', () => { var unboundInputOnChange = function() { expect(this).toBe(undefined); @@ -664,12 +721,12 @@ describe('ReactDOMInput', () => { it('should warn with checked and no onChange handler with readOnly specified', () => { ReactTestUtils.renderIntoDocument( - , + , ); expectDev(console.error.calls.count()).toBe(0); ReactTestUtils.renderIntoDocument( - , + , ); expectDev(console.error.calls.count()).toBe(1); }); diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMTextarea-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMTextarea-test.js index 254973dcc751..110a0b0e5647 100644 --- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMTextarea-test.js +++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMTextarea-test.js @@ -99,7 +99,7 @@ describe('ReactDOMTextarea', () => { }); it('should display `value` of number 0', () => { - var stub =