diff --git a/src/browser/ui/dom/components/ReactDOMInput.js b/src/browser/ui/dom/components/ReactDOMInput.js
index 49f783c1e1264..b1910d1186295 100644
--- a/src/browser/ui/dom/components/ReactDOMInput.js
+++ b/src/browser/ui/dom/components/ReactDOMInput.js
@@ -19,6 +19,8 @@ var ReactClass = require('ReactClass');
var ReactElement = require('ReactElement');
var ReactMount = require('ReactMount');
var ReactUpdates = require('ReactUpdates');
+var ExecutionEnvironment = require('ExecutionEnvironment');
+var isTextInputElement = require('isTextInputElement');
var assign = require('Object.assign');
var findDOMNode = require('findDOMNode');
@@ -27,6 +29,11 @@ var invariant = require('invariant');
var input = ReactElement.createFactory('input');
var instancesByReactID = {};
+var hasNoisyInputEvent = false;
+
+if (ExecutionEnvironment.canUseDOM) {
+ hasNoisyInputEvent = 'documentMode' in document && document.documentMode > 9;
+}
function forceUpdateIfMounted() {
/*jshint validthis:true */
@@ -35,6 +42,15 @@ function forceUpdateIfMounted() {
}
}
+
+function isIEInputEvent(event) {
+ return (
+ hasNoisyInputEvent &&
+ event.nativeEvent.type === 'input' &&
+ isTextInputElement(event.target)
+ );
+}
+
/**
* Implements an native component that allows setting these optional
* props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
@@ -57,8 +73,20 @@ var ReactDOMInput = ReactClass.createClass({
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
+ componentWillMount: function() {
+ var value = LinkedValueUtils.getValue(this.props);
+ var defaultValue = this.props.defaultValue;
+
+ if (defaultValue == null) {
+ defaultValue = '';
+ }
+
+ this._lastValue = value != null ? value : defaultValue;
+ },
+
getInitialState: function() {
var defaultValue = this.props.defaultValue;
+
return {
initialChecked: this.props.defaultChecked || false,
initialValue: defaultValue != null ? defaultValue : null
@@ -115,6 +143,22 @@ var ReactDOMInput = ReactClass.createClass({
_handleChange: function(event) {
var returnValue;
var onChange = LinkedValueUtils.getOnChange(this.props);
+
+ // IE 10+ fire input events when setting/unsetting a placeholder
+ // we guard against it by checking if the next and
+ // last values are both empty and bailing out of the change
+ // https://github.com/facebook/react/issues/3484
+ if (isIEInputEvent(event)) {
+ var lastValue = this._lastValue;
+
+ this._lastValue = event.target.value;
+
+ if ( event.target.value === '' && lastValue === '') {
+ event.stopPropagation();
+ return undefined;
+ }
+ }
+
if (onChange) {
returnValue = onChange.call(this, event);
}
diff --git a/src/browser/ui/dom/components/ReactDOMTextarea.js b/src/browser/ui/dom/components/ReactDOMTextarea.js
index 0261005c40ca4..666a1e1716668 100644
--- a/src/browser/ui/dom/components/ReactDOMTextarea.js
+++ b/src/browser/ui/dom/components/ReactDOMTextarea.js
@@ -18,6 +18,7 @@ var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
var ReactClass = require('ReactClass');
var ReactElement = require('ReactElement');
var ReactUpdates = require('ReactUpdates');
+var ExecutionEnvironment = require('ExecutionEnvironment');
var assign = require('Object.assign');
var findDOMNode = require('findDOMNode');
@@ -26,6 +27,11 @@ var invariant = require('invariant');
var warning = require('warning');
var textarea = ReactElement.createFactory('textarea');
+var hasNoisyInputEvent = false;
+
+if (ExecutionEnvironment.canUseDOM) {
+ hasNoisyInputEvent = 'documentMode' in document && document.documentMode > 9;
+}
function forceUpdateIfMounted() {
/*jshint validthis:true */
@@ -34,6 +40,13 @@ function forceUpdateIfMounted() {
}
}
+function isIEInputEvent(event) {
+ return (
+ hasNoisyInputEvent &&
+ event.nativeEvent.type === 'input'
+ );
+}
+
/**
* Implements a