@samitouri / QOS-React / commits / d92114b98e

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