@@ -22,6 +22,7 @@ var EventConstants = require('EventConstants');
2222var EventPluginHub = require ( 'EventPluginHub' ) ;
2323var EventPropagators = require ( 'EventPropagators' ) ;
2424var ExecutionEnvironment = require ( 'ExecutionEnvironment' ) ;
25+ var ReactUpdates = require ( 'ReactUpdates' ) ;
2526var SyntheticEvent = require ( 'SyntheticEvent' ) ;
2627
2728var isEventSupported = require ( 'isEventSupported' ) ;
@@ -73,10 +74,21 @@ function manualDispatchChangeEvent(nativeEvent) {
7374 ) ;
7475 EventPropagators . accumulateTwoPhaseDispatches ( event ) ;
7576
76- // If change bubbled, we'd just bind to it like all the other events
77- // and have it go through ReactEventTopLevelCallback. Since it doesn't, we
78- // manually listen for the change event and so we have to enqueue and
77+ // If change and propertychange bubbled, we'd just bind to it like all the
78+ // other events and have it go through ReactEventTopLevelCallback. Since it
79+ // doesn't, we manually listen for the events and so we have to enqueue and
7980 // process the abstract event manually.
81+ //
82+ // Batching is necessary here in order to ensure that all event handlers run
83+ // before the next rerender (including event handlers attached to ancestor
84+ // elements instead of directly on the input). Without this, controlled
85+ // components don't work properly in conjunction with event bubbling because
86+ // the component is rerendered and the value reverted before all the event
87+ // handlers can run. See https://github.com/facebook/react/issues/708.
88+ ReactUpdates . batchedUpdates ( runEventInBatch , event ) ;
89+ }
90+
91+ function runEventInBatch ( event ) {
8092 EventPluginHub . enqueueEvents ( event ) ;
8193 EventPluginHub . processEventQueue ( ) ;
8294}
0 commit comments