Resubmit: Fix updateWrapper causing re-render textarea, even though their data (#13643)
* fix updateWrapper causing re-render textarea, even though their data has not changed * fix updateWrapper causing re-render textarea, even though their data, prettier-all * minor changes to updateWrapper, add test
Nathan Hunzaker committed
Sep 14, 2018 at 16:09 UTC
d92114b98e8509a9fac8ad4f56110020fa8d6987
2 files changed
+44
-3
packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
+40
@@ -426,6 +426,46 @@ describe('ReactDOMTextarea', () => {
426
ReactDOM.render(<textarea value={undefined} />, container);
427
});
428
429
+ it('does not set textContent if value is unchanged', () => {
430
+ const container = document.createElement('div');
431
+ let node;
432
+ let instance;
433
+ // Setting defaultValue on a textarea is equivalent to setting textContent,
434
+ // and is the method we currently use, so we can observe if defaultValue is
435
+ // is set to determine if textContent is being recreated.
436
+ // https://html.spec.whatwg.org/#the-textarea-element
437
+ let defaultValue;
438
+ const set = jest.fn(value => {
439
+ defaultValue = value;
440
+ });
441
+ const get = jest.fn(value => {
442
+ return defaultValue;
443
+ });
444
+ class App extends React.Component {
445
+ state = {count: 0, text: 'foo'};
446
+ componentDidMount() {
447
+ instance = this;
448
+ }
449
+ render() {
450
+ return (
451
+ <div>
452
+ <span>{this.state.count}</span>
453
+ <textarea
454
+ ref={n => (node = n)}
455
+ value="foo"
456
+ onChange={emptyFunction}
457
+ />
458
+ </div>
459
+ );
460
+ }
461
+ }
462
+ ReactDOM.render(<App />, container);
463
+ defaultValue = node.defaultValue;
464
+ Object.defineProperty(node, 'defaultValue', {get, set});
465
+ instance.setState({count: 1});
466
+ expect(set.mock.calls.length).toBe(0);
467
+ });
468
+
469
describe('When given a Symbol value', () => {
470
it('treats initial Symbol value as an empty string', () => {
471
const container = document.createElement('div');
packages/react-dom/src/client/ReactDOMTextarea.js
+4
-3
@@ -128,6 +128,7 @@ export function initWrapperState(element: Element, props: Object) {
128
export function updateWrapper(element: Element, props: Object) {
129
const node = ((element: any): TextAreaWithWrapperState);
130
const value = getToStringValue(props.value);
131
+ const defaultValue = getToStringValue(props.defaultValue);
132
if (value != null) {
133
// Cast `value` to a string to ensure the value is set correctly. While
134
// browsers typically do this as necessary, jsdom doesn't.
@@ -136,12 +137,12 @@ export function updateWrapper(element: Element, props: Object) {
137
if (newValue !== node.value) {
138
node.value = newValue;
139
}
139
- if (props.defaultValue == null) {
140
+ if (props.defaultValue == null && node.defaultValue !== newValue) {
141
node.defaultValue = newValue;
142
}
143
}
143
- if (props.defaultValue != null) {
144
- node.defaultValue = toString(getToStringValue(props.defaultValue));
144
+ if (defaultValue != null) {
145
+ node.defaultValue = toString(defaultValue);
146
}
147
}
148