Skip to content

Commit 74044e0

Browse files
nhunzakeraweary
authored andcommitted
Inputs should not mutate value on type conversion (#9806)
This is a follow-up on #9584 (comment). There is no need to assign the value property of an input if the value property of the React component changes types, but stringifies to the same value. For example: ```javascript DOM.render(<input value="true" />, el) DOM.render(<input value={true} />, el) ``` In this case, the assignment to `input.value` will always be cast to the string "true". There is no need to perform this assignment. Particularly when we already cast the value to a string later: ```javascript // Cast `value` to a string to ensure the value is set correctly. While // browsers typically do this as necessary, jsdom doesn't. node.value = '' + value; ```
1 parent 80bdebc commit 74044e0

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

scripts/fiber/tests-passing.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,8 @@ src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
15361536
* should allow setting `value` to `false`
15371537
* should allow setting `value` to `objToString`
15381538
* should not incur unnecessary DOM mutations
1539+
* should not incur unnecessary DOM mutations for numeric type conversion
1540+
* should not incur unnecessary DOM mutations for the boolean type conversion
15391541
* should properly control a value of number `0`
15401542
* should properly control 0.0 for a text input
15411543
* should properly control 0.0 for a number input

src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ var ReactDOMInput = {
209209
// browsers typically do this as necessary, jsdom doesn't.
210210
node.value = '' + value;
211211
}
212-
} else if (node.value !== value) {
212+
} else if (node.value !== '' + value) {
213213
// Cast `value` to a string to ensure the value is set correctly. While
214214
// browsers typically do this as necessary, jsdom doesn't.
215215
node.value = '' + value;

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

+40
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,46 @@ describe('ReactDOMInput', () => {
471471
expect(nodeValueSetter.mock.calls.length).toBe(1);
472472
});
473473

474+
it('should not incur unnecessary DOM mutations for numeric type conversion', () => {
475+
var container = document.createElement('div');
476+
ReactDOM.render(<input value="0" />, container);
477+
478+
var node = container.firstChild;
479+
var nodeValue = '0';
480+
var nodeValueSetter = jest.genMockFn();
481+
Object.defineProperty(node, 'value', {
482+
get: function() {
483+
return nodeValue;
484+
},
485+
set: nodeValueSetter.mockImplementation(function(newValue) {
486+
nodeValue = newValue;
487+
}),
488+
});
489+
490+
ReactDOM.render(<input value={0} />, container);
491+
expect(nodeValueSetter.mock.calls.length).toBe(0);
492+
});
493+
494+
it('should not incur unnecessary DOM mutations for the boolean type conversion', () => {
495+
var container = document.createElement('div');
496+
ReactDOM.render(<input value="true" />, container);
497+
498+
var node = container.firstChild;
499+
var nodeValue = 'true';
500+
var nodeValueSetter = jest.genMockFn();
501+
Object.defineProperty(node, 'value', {
502+
get: function() {
503+
return nodeValue;
504+
},
505+
set: nodeValueSetter.mockImplementation(function(newValue) {
506+
nodeValue = newValue;
507+
}),
508+
});
509+
510+
ReactDOM.render(<input value={true} />, container);
511+
expect(nodeValueSetter.mock.calls.length).toBe(0);
512+
});
513+
474514
it('should properly control a value of number `0`', () => {
475515
var stub = <input type="text" value={0} onChange={emptyFunction} />;
476516
stub = ReactTestUtils.renderIntoDocument(stub);

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ var ReactDOMInput = {
201201
// browsers typically do this as necessary, jsdom doesn't.
202202
node.value = '' + value;
203203
}
204-
} else if (node.value !== value) {
204+
} else if (node.value !== '' + value) {
205205
// Cast `value` to a string to ensure the value is set correctly. While
206206
// browsers typically do this as necessary, jsdom doesn't.
207207
node.value = '' + value;

0 commit comments

Comments
 (0)