From eee3980749c13f8f80ed7cf839b325a2d56ffad4 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 12 Jul 2013 15:40:18 -0700 Subject: [PATCH] Stringify `value` in ReactDOMInput / ChangeEventPlugin This fixes two bugs related to string-casting in React: # Setting `` would use an empty `value` because `0` is falsey. # Using `onChange` and `setState` with non-strings could lead to an infinite loop. The latter is possible with controlled inputs when: - User changes input value. - `onpropertychange` fires. - `ChangeEventPlugin` dispatches `onChange`. - A handler responds via `this.setState` with a non-string value (e.g. a number). - The input re-renders and re-sets `value`. - The new `value` is not a string, but the current `value` (read from the element) is cast to a string automatically by the browser. - This triggers another `onpropertychange`. - `ChangeEventPlugin` dispatches another `onChange`. - ... --- src/dom/components/ReactDOMInput.js | 7 +++++-- src/eventPlugins/ChangeEventPlugin.js | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/dom/components/ReactDOMInput.js b/src/dom/components/ReactDOMInput.js index 2d552fc923..e6ba3ed3df 100644 --- a/src/dom/components/ReactDOMInput.js +++ b/src/dom/components/ReactDOMInput.js @@ -62,7 +62,8 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ }, getValue: function() { - return this.props.value != null ? this.props.value : this.state.value; + // Cast `this.props.value` to a string so equality checks pass. + return this.props.value != null ? '' + this.props.value : this.state.value; }, render: function() { @@ -85,10 +86,12 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ ); } if (this.props.value != null) { + // Cast `this.props.value` to a string so falsey values that cast to + // truthy strings are not ignored. DOMPropertyOperations.setValueForProperty( rootNode, 'value', - this.props.value || '' + '' + this.props.value || '' ); } }, diff --git a/src/eventPlugins/ChangeEventPlugin.js b/src/eventPlugins/ChangeEventPlugin.js index 6bb13d5e0e..835651fecd 100644 --- a/src/eventPlugins/ChangeEventPlugin.js +++ b/src/eventPlugins/ChangeEventPlugin.js @@ -169,7 +169,8 @@ var newValueProp = { return activeElementValueProp.get.call(this); }, set: function(val) { - activeElementValue = val; + // Cast to a string so we can do equality checks. + activeElementValue = '' + val; activeElementValueProp.set.call(this, val); } }; @@ -231,7 +232,7 @@ function handlePropertyChange(nativeEvent) { /** * If a `change` event should be fired, returns the target's ID. */ -function getTargetIDForInputEvent( +function getTargetIDForInputEvent( topLevelType, topLevelTarget, topLevelTargetID) {