Skip to content

Commit ff1e9d8

Browse files
author
jim
committed
Cleanup and bug fixes for merge.
1 parent 574328a commit ff1e9d8

File tree

6 files changed

+59
-16
lines changed

6 files changed

+59
-16
lines changed

src/renderers/dom/client/wrappers/ReactDOMInput.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ var ReactDOMInput = {
7575
}, props, {
7676
defaultChecked: undefined,
7777
defaultValue: undefined,
78-
value: value != null ? value : props.defaultValue,
78+
value: value != null ? value : inst._wrapperState.initialValue,
7979
checked: checked != null ? checked : inst._wrapperState.initialChecked,
8080
onChange: inst._wrapperState.onChange,
8181
});
@@ -138,8 +138,10 @@ var ReactDOMInput = {
138138
warnIfValueIsNull(props);
139139
}
140140

141+
var defaultValue = props.defaultValue;
141142
inst._wrapperState = {
142143
initialChecked: props.defaultChecked || false,
144+
initialValue: props.value ? props.value : defaultValue,
143145
listeners: null,
144146
onChange: _handleChange.bind(inst),
145147
};

src/renderers/dom/client/wrappers/ReactDOMTextarea.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,11 @@ var ReactDOMTextarea = {
100100

101101
// The value can be a boolean or object so that's why it's
102102
// forced to be a string.
103+
defaultValue = '' + (value != null ? value : defaultValue);
103104
var nativeProps = Object.assign({}, props, {
104-
defaultValue: '' + (value != null ? value : defaultValue),
105+
defaultValue: defaultValue,
105106
value: undefined,
106-
children: undefined,
107+
children: defaultValue,
107108
onChange: inst._wrapperState.onChange,
108109
});
109110

src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe('ReactDOMInput', function() {
1818
var EventConstants;
1919
var React;
2020
var ReactDOM;
21+
var ReactDOMServer;
2122
var ReactDOMFeatureFlags;
2223
var ReactLink;
2324
var ReactTestUtils;
@@ -27,6 +28,7 @@ describe('ReactDOMInput', function() {
2728
EventConstants = require('EventConstants');
2829
React = require('React');
2930
ReactDOM = require('ReactDOM');
31+
ReactDOMServer = require('ReactDOMServer');
3032
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
3133
ReactLink = require('ReactLink');
3234
ReactTestUtils = require('ReactTestUtils');
@@ -67,7 +69,7 @@ describe('ReactDOMInput', function() {
6769

6870
ReactDOM.render(<input type="text" defaultValue="1" />, container);
6971

70-
expect(node.value).toBe('1');
72+
expect(node.value).toBe('0');
7173
});
7274

7375
it('should take `defaultValue` when changing to uncontrolled input', function() {
@@ -79,7 +81,14 @@ describe('ReactDOMInput', function() {
7981

8082
ReactDOM.render(<input type="text" defaultValue="1" />, container);
8183

82-
expect(node.value).toBe('1');
84+
expect(node.value).toBe('0');
85+
});
86+
87+
it('should render value for SSR', function() {
88+
var image = ReactDOMServer.renderToString(<input type="text" defaultValue="1" />);
89+
var div = document.createElement('div');
90+
div.innerHTML = image;
91+
expect(div.firstChild.getAttribute('value')).toBe('1');
8392
});
8493

8594
it('should display "foobar" for `defaultValue` of `objToString`', function() {

src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js

+19-10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var emptyFunction = require('emptyFunction');
1616
describe('ReactDOMTextarea', function() {
1717
var React;
1818
var ReactDOM;
19+
var ReactDOMServer;
1920
var ReactLink;
2021
var ReactTestUtils;
2122

@@ -24,6 +25,7 @@ describe('ReactDOMTextarea', function() {
2425
beforeEach(function() {
2526
React = require('React');
2627
ReactDOM = require('ReactDOM');
28+
ReactDOMServer = require('ReactDOMServer');
2729
ReactLink = require('ReactLink');
2830
ReactTestUtils = require('ReactTestUtils');
2931

@@ -50,7 +52,7 @@ describe('ReactDOMTextarea', function() {
5052

5153
// Changing `defaultValue` should change if no value set.
5254
renderTextarea(<textarea defaultValue="gorilla" />, container, true);
53-
expect(node.value).toEqual('gorilla');
55+
expect(node.value).toEqual('giraffe');
5456

5557
node.value = 'cat';
5658

@@ -113,6 +115,13 @@ describe('ReactDOMTextarea', function() {
113115
expect(node.value).toEqual('gorilla');
114116
});
115117

118+
it('should render value for SSR', function() {
119+
var image = ReactDOMServer.renderToString(<textarea defaultValue="1" />);
120+
var div = document.createElement('div');
121+
div.innerHTML = image;
122+
expect(div.firstChild.innerHTML).toBe('1');
123+
});
124+
116125
it('should allow setting `value` to `true`', function() {
117126
var container = document.createElement('div');
118127
var stub = <textarea value="giraffe" onChange={emptyFunction} />;
@@ -163,27 +172,27 @@ describe('ReactDOMTextarea', function() {
163172
it('should take updates to `defaultValue` for uncontrolled textarea', function() {
164173
var container = document.createElement('div');
165174

166-
var node = ReactDOM.render(<textarea type="text" defaultValue="0" />, container);
175+
var node = ReactDOM.render(<textarea defaultValue="0" />, container);
167176

168177
expect(node.value).toBe('0');
169178

170-
ReactDOM.render(<textarea type="text" defaultValue="1" />, container);
179+
ReactDOM.render(<textarea defaultValue="1" />, container);
171180

172-
expect(node.value).toBe('1');
181+
expect(node.value).toBe('0');
173182
});
174183

175184
it('should take updates to children in lieu of `defaultValue` for uncontrolled textarea', function() {
176185
var container = document.createElement('div');
177186

178-
var node = ReactDOM.render(<textarea type="text" defaultValue="0" />, container);
187+
var node = ReactDOM.render(<textarea defaultValue="0" />, container);
179188

180189
expect(node.value).toBe('0');
181190

182191
spyOn(console, 'error'); // deprecation warning for `children` content
183192

184-
ReactDOM.render(<textarea type="text">1</textarea>, container);
193+
ReactDOM.render(<textarea>1</textarea>, container);
185194

186-
expect(node.value).toBe('1');
195+
expect(node.value).toBe('0');
187196
});
188197

189198
it('should not incur unnecessary DOM mutations', function() {
@@ -228,9 +237,9 @@ describe('ReactDOMTextarea', function() {
228237
expect(console.error.argsForCall.length).toBe(1);
229238
expect(node.value).toBe('giraffe');
230239

231-
// Changing children should cause value to change (new behavior of `defaultValue`)
240+
// Changing children should do nothing, it functions like `defaultValue`.
232241
stub = ReactDOM.render(<textarea>gorilla</textarea>, container);
233-
expect(node.value).toEqual('gorilla');
242+
expect(node.value).toEqual('giraffe');
234243
});
235244

236245
it('should not keep value when switching to uncontrolled element if not changed', function() {
@@ -242,7 +251,7 @@ describe('ReactDOMTextarea', function() {
242251

243252
ReactDOM.render(<textarea defaultValue="gorilla"></textarea>, container);
244253

245-
expect(node.value).toEqual('gorilla');
254+
expect(node.value).toEqual('kitten');
246255
});
247256

248257
it('should keep value when switching to uncontrolled element if changed', function() {

src/renderers/dom/shared/DOMPropertyOperations.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,16 @@ var DOMPropertyOperations = {
153153
('' + node[propName]) !== ('' + value)) {
154154
// Contrary to `setAttribute`, object properties are properly
155155
// `toString`ed by IE8/9.
156-
node[propName] = value;
156+
157+
if (propName === 'defaultValue' && (node._tag === 'textarea' || node._tag === 'input')) {
158+
// defaultValue is a special property because it can perturb the value property
159+
var tmp = node.value;
160+
node[propName] = value;
161+
node.value = tmp;
162+
}
163+
else {
164+
node[propName] = value;
165+
}
157166
}
158167
} else {
159168
var attributeName = propertyInfo.attributeName;

src/renderers/dom/shared/ReactDOMComponent.js

+13
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,13 @@ function trapBubbledEventsLocal() {
345345
}
346346
}
347347

348+
function initializeInitialInputValue() {
349+
var inst = this;
350+
invariant(inst._rootNodeID, 'Must be mounted to initialize initial input value');
351+
var node = getNode(inst);
352+
node.value = node.defaultValue;
353+
}
354+
348355
function postUpdateSelectWrapper() {
349356
ReactDOMSelect.postUpdateWrapper(this);
350357
}
@@ -488,6 +495,9 @@ ReactDOMComponent.Mixin = {
488495
ReactDOMInput.mountWrapper(this, props, nativeParent);
489496
props = ReactDOMInput.getNativeProps(this, props);
490497
transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
498+
if (!props.value && props.defaultValue) {
499+
transaction.getReactMountReady().enqueue(initializeInitialInputValue, this);
500+
}
491501
break;
492502
case 'option':
493503
ReactDOMOption.mountWrapper(this, props, nativeParent);
@@ -502,6 +512,9 @@ ReactDOMComponent.Mixin = {
502512
ReactDOMTextarea.mountWrapper(this, props, nativeParent);
503513
props = ReactDOMTextarea.getNativeProps(this, props);
504514
transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
515+
if (!props.value && props.defaultValue) {
516+
transaction.getReactMountReady().enqueue(initializeInitialInputValue, this);
517+
}
505518
break;
506519
}
507520

0 commit comments

Comments
 (0)