From 2df2023b20ac4752c63dbaef3d0766a9e72e17c1 Mon Sep 17 00:00:00 2001 From: Nate Hunzaker Date: Thu, 15 Sep 2016 20:24:25 -0400 Subject: [PATCH 1/2] Only assign defaultValue if it has changed. --- .../dom/client/wrappers/ReactDOMInput.js | 6 ++++- .../wrappers/__tests__/ReactDOMInput-test.js | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index 04814bd869df3..8bf32fe4131f3 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -213,7 +213,11 @@ var ReactDOMInput = { } } else { if (props.value == null && props.defaultValue != null) { - node.defaultValue = '' + props.defaultValue; + // Assigning defaultValue causes side-effects on value, which can cause + // unexpected value changes and selections skipping. A quick check avoids this + if (node.defaultValue !== '' + props.defaultValue) { + node.defaultValue = '' + props.defaultValue; + } } if (props.checked == null && props.defaultChecked != null) { node.defaultChecked = !!props.defaultChecked; diff --git a/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js index 04a8b3a1f4def..a09d63b0608d4 100644 --- a/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js +++ b/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js @@ -51,6 +51,28 @@ describe('ReactDOMInput', () => { expect(node.value).toBe('0'); }); + it('only assigns defaultValue if it changes', () => { + class Test extends React.Component { + render() { + return (); + } + } + + var component = ReactTestUtils.renderIntoDocument(); + var node = ReactDOM.findDOMNode(component); + + Object.defineProperty(node, 'defaultValue', { + get() { + return '0'; + }, + set(value) { + throw new Error(`defaultValue was assigned ${value}, but it did not change!`); + }, + }); + + component.forceUpdate(); + }); + it('should display "true" for `defaultValue` of `true`', () => { var stub = ; stub = ReactTestUtils.renderIntoDocument(stub); From 8f8a833bba6d7eefdb2716c185a62f3c62915cbc Mon Sep 17 00:00:00 2001 From: Nathan Hunzaker Date: Wed, 12 Oct 2016 14:11:15 -0400 Subject: [PATCH 2/2] Improve comment about reason for defaultValue conditional assignment --- src/renderers/dom/client/wrappers/ReactDOMInput.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index 8bf32fe4131f3..8d1ad6ec5506a 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -213,8 +213,14 @@ var ReactDOMInput = { } } else { if (props.value == null && props.defaultValue != null) { - // Assigning defaultValue causes side-effects on value, which can cause - // unexpected value changes and selections skipping. A quick check avoids this + // In Chrome, assigning defaultValue to certain input types triggers input validation. + // For number inputs, the display value loses trailing decimal points. For email inputs, + // Chrome raises "The specified value is not a valid email address". + // + // Here we check to see if the defaultValue has actually changed, avoiding these problems + // when the user is inputting text + // + // https://github.com/facebook/react/issues/7253 if (node.defaultValue !== '' + props.defaultValue) { node.defaultValue = '' + props.defaultValue; }