diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index e309fd6191a76..031faf14b6673 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -24,6 +24,7 @@ var instancesByReactID = {}; var didWarnValueLink = false; var didWarnCheckedLink = false; +var didWarnValueNull = false; function forceUpdateIfMounted() { if (this._rootNodeID) { @@ -32,6 +33,19 @@ function forceUpdateIfMounted() { } } +function warnIfValueIsNull(props) { + if (props != null && props.value === null && !didWarnValueNull) { + warning( + false, + '`value` prop on `input` should not be null. ' + + 'Consider using the empty string to clear the component or' + + ' `undefined` for uncontrolled components.' + ); + + didWarnValueNull = true; + } +} + /** * Implements an native component that allows setting these optional * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. @@ -86,6 +100,7 @@ var ReactDOMInput = { ); didWarnCheckedLink = true; } + warnIfValueIsNull(props); } var defaultValue = props.defaultValue; @@ -108,6 +123,10 @@ var ReactDOMInput = { updateWrapper: function(inst) { var props = inst._currentElement.props; + if (__DEV__) { + warnIfValueIsNull(props); + } + // TODO: Shouldn't this be getChecked(props)? var checked = props.checked; if (checked != null) { diff --git a/src/renderers/dom/client/wrappers/ReactDOMSelect.js b/src/renderers/dom/client/wrappers/ReactDOMSelect.js index 96c1098c66370..7d970714a3a5d 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMSelect.js +++ b/src/renderers/dom/client/wrappers/ReactDOMSelect.js @@ -19,6 +19,7 @@ var assign = require('Object.assign'); var warning = require('warning'); var didWarnValueLink = false; +var didWarnValueNull = false; function updateOptionsIfPendingUpdateAndMounted() { if (this._rootNodeID && this._wrapperState.pendingUpdate) { @@ -43,6 +44,19 @@ function getDeclarationErrorAddendum(owner) { return ''; } +function warnIfValueIsNull(props) { + if (props != null && props.value === null && !didWarnValueNull) { + warning( + false, + '`value` prop on `select` should not be null. ' + + 'Consider using the empty string to clear the component or' + + ' `undefined` for uncontrolled components.' + ); + + didWarnValueNull = true; + } +} + var valuePropNames = ['value', 'defaultValue']; /** @@ -153,6 +167,7 @@ var ReactDOMSelect = { mountWrapper: function(inst, props) { if (__DEV__) { checkSelectPropTypes(inst, props); + warnIfValueIsNull(props); } var value = LinkedValueUtils.getValue(props); @@ -172,6 +187,9 @@ var ReactDOMSelect = { postUpdateWrapper: function(inst) { var props = inst._currentElement.props; + if (__DEV__) { + warnIfValueIsNull(props); + } // After the initial mount, we control selected-ness manually so don't pass // this value down diff --git a/src/renderers/dom/client/wrappers/ReactDOMTextarea.js b/src/renderers/dom/client/wrappers/ReactDOMTextarea.js index 26ac1dd4de626..f5a1b97806d52 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMTextarea.js +++ b/src/renderers/dom/client/wrappers/ReactDOMTextarea.js @@ -20,6 +20,7 @@ var invariant = require('invariant'); var warning = require('warning'); var didWarnValueLink = false; +var didWarnValueNull = false; function forceUpdateIfMounted() { if (this._rootNodeID) { @@ -28,6 +29,19 @@ function forceUpdateIfMounted() { } } +function warnIfValueIsNull(props) { + if (props != null && props.value === null && !didWarnValueNull) { + warning( + false, + '`value` prop on `textarea` should not be null. ' + + 'Consider using the empty string to clear the component or' + + ' `undefined` for uncontrolled components.' + ); + + didWarnValueNull = true; + } +} + /** * Implements a