From f6c393c0e8c3693eaa75b5d64cb57488dfa44a03 Mon Sep 17 00:00:00 2001 From: Jim Sproch Date: Mon, 4 Apr 2016 10:39:07 -0700 Subject: [PATCH] Cleanup and bug fixes for merge. --- .../dom/client/wrappers/ReactDOMInput.js | 30 ++++++- .../dom/client/wrappers/ReactDOMTextarea.js | 86 +++++++++++-------- .../wrappers/__tests__/ReactDOMInput-test.js | 14 ++- .../__tests__/ReactDOMTextarea-test.js | 40 ++++++--- .../dom/shared/HTMLDOMPropertyConfig.js | 1 - src/renderers/dom/shared/ReactDOMComponent.js | 28 +++++- .../__tests__/ReactDOMComponent-test.js | 2 +- .../__tests__/ReactStatelessComponent-test.js | 2 +- 8 files changed, 147 insertions(+), 56 deletions(-) diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index 56814142e39dc..a3b58e82a20c7 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -75,7 +75,7 @@ var ReactDOMInput = { }, props, { defaultChecked: undefined, defaultValue: undefined, - value: value != null ? value : props.defaultValue, + value: value != null ? value : inst._wrapperState.initialValue, checked: checked != null ? checked : inst._wrapperState.initialChecked, onChange: inst._wrapperState.onChange, }); @@ -138,8 +138,10 @@ var ReactDOMInput = { warnIfValueIsNull(props); } + var defaultValue = props.defaultValue; inst._wrapperState = { - initialChecked: props.defaultChecked || false, + initialChecked: props.checked != null ? props.checked : props.defaultChecked, + initialValue: props.value != null ? props.value : defaultValue, listeners: null, onChange: _handleChange.bind(inst), }; @@ -215,6 +217,30 @@ var ReactDOMInput = { if (newValue !== node.value) { node.value = newValue; } + } else { + ReactDOMInput.postUpdateWrapper(inst); + } + }, + + postUpdateWrapper: function(inst) { + var props = inst._currentElement.props; + if (!props.value && props.defaultValue) { + invariant(inst._rootNodeID, 'Must be mounted to initialize initial input value'); + var node = ReactDOMComponentTree.getNodeFromInstance(inst); + if (node.defaultValue !== props.defaultValue) { + var tmp = node.value; + node.defaultValue = '' + props.defaultValue; + node.value = tmp; + } + } + if (!props.checked && props.defaultChecked) { + invariant(inst._rootNodeID, 'Must be mounted to initialize initial input value'); + var node = ReactDOMComponentTree.getNodeFromInstance(inst); + if (node.defaultChecked !== props.defaultChecked) { + var tmp = node.checked; + node.defaultChecked = '' + props.defaultChecked; + node.checked = tmp; + } } }, }; diff --git a/src/renderers/dom/client/wrappers/ReactDOMTextarea.js b/src/renderers/dom/client/wrappers/ReactDOMTextarea.js index 37213bf319c0d..db05f9a0fd416 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMTextarea.js +++ b/src/renderers/dom/client/wrappers/ReactDOMTextarea.js @@ -66,44 +66,12 @@ var ReactDOMTextarea = { var value = LinkedValueUtils.getValue(props); - // only bother fetching default value if we're going to use it - if (value == null) { - var defaultValue = props.defaultValue; - // TODO (yungsters): Remove support for children content in , container); + ReactDOM.render(, container); - expect(node.value).toBe('1'); + expect(node.value).toBe('0'); }); it('should not incur unnecessary DOM mutations', function() { @@ -228,9 +246,9 @@ describe('ReactDOMTextarea', function() { expect(console.error.argsForCall.length).toBe(1); expect(node.value).toBe('giraffe'); - // Changing children should cause value to change (new behavior of `defaultValue`) + // Changing children should do nothing, it functions like `defaultValue`. stub = ReactDOM.render(, container); - expect(node.value).toEqual('gorilla'); + expect(node.value).toEqual('giraffe'); }); it('should not keep value when switching to uncontrolled element if not changed', function() { @@ -242,7 +260,7 @@ describe('ReactDOMTextarea', function() { ReactDOM.render(, container); - expect(node.value).toEqual('gorilla'); + expect(node.value).toEqual('kitten'); }); it('should keep value when switching to uncontrolled element if changed', function() { diff --git a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js index 60f87e2586238..f5e0258d293a6 100644 --- a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js +++ b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js @@ -61,7 +61,6 @@ var HTMLDOMPropertyConfig = { data: 0, // For `` acts as `src`. dateTime: 0, default: HAS_BOOLEAN_VALUE, - defaultValue: MUST_USE_PROPERTY, defer: HAS_BOOLEAN_VALUE, dir: 0, disabled: HAS_BOOLEAN_VALUE, diff --git a/src/renderers/dom/shared/ReactDOMComponent.js b/src/renderers/dom/shared/ReactDOMComponent.js index 808706d62b8dc..1bd004310e67c 100644 --- a/src/renderers/dom/shared/ReactDOMComponent.js +++ b/src/renderers/dom/shared/ReactDOMComponent.js @@ -349,6 +349,14 @@ function postUpdateSelectWrapper() { ReactDOMSelect.postUpdateWrapper(this); } +function postUpdateTextareaWrapper() { + ReactDOMTextarea.postUpdateWrapper(this); +} + +function postUpdateInputWrapper() { + ReactDOMInput.postUpdateWrapper(this); +} + // For HTML, certain tags should omit their close tag. We keep a whitelist for // those special-case tags. @@ -488,6 +496,7 @@ ReactDOMComponent.Mixin = { ReactDOMInput.mountWrapper(this, props, nativeParent); props = ReactDOMInput.getNativeProps(this, props); transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); + transaction.getReactMountReady().enqueue(postUpdateInputWrapper, this); break; case 'option': ReactDOMOption.mountWrapper(this, props, nativeParent); @@ -502,6 +511,7 @@ ReactDOMComponent.Mixin = { ReactDOMTextarea.mountWrapper(this, props, nativeParent); props = ReactDOMTextarea.getNativeProps(this, props); transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this); + transaction.getReactMountReady().enqueue(postUpdateTextareaWrapper, this); break; } @@ -811,10 +821,20 @@ ReactDOMComponent.Mixin = { context ); - if (this._tag === 'select') { - //