Skip to content

Commit

Permalink
Resubmit: Fix updateWrapper causing re-render textarea, even though t…
Browse files Browse the repository at this point in the history
…heir 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
  • Loading branch information
nhunzaker committed Sep 14, 2018
1 parent 0c9c591 commit d92114b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
40 changes: 40 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,46 @@ describe('ReactDOMTextarea', () => {
ReactDOM.render(<textarea value={undefined} />, container);
});

it('does not set textContent if value is unchanged', () => {
const container = document.createElement('div');
let node;
let instance;
// Setting defaultValue on a textarea is equivalent to setting textContent,
// and is the method we currently use, so we can observe if defaultValue is
// is set to determine if textContent is being recreated.
// https://html.spec.whatwg.org/#the-textarea-element
let defaultValue;
const set = jest.fn(value => {
defaultValue = value;
});
const get = jest.fn(value => {
return defaultValue;
});
class App extends React.Component {
state = {count: 0, text: 'foo'};
componentDidMount() {
instance = this;
}
render() {
return (
<div>
<span>{this.state.count}</span>
<textarea
ref={n => (node = n)}
value="foo"
onChange={emptyFunction}
/>
</div>
);
}
}
ReactDOM.render(<App />, container);
defaultValue = node.defaultValue;
Object.defineProperty(node, 'defaultValue', {get, set});
instance.setState({count: 1});
expect(set.mock.calls.length).toBe(0);
});

describe('When given a Symbol value', () => {
it('treats initial Symbol value as an empty string', () => {
const container = document.createElement('div');
Expand Down
7 changes: 4 additions & 3 deletions packages/react-dom/src/client/ReactDOMTextarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export function initWrapperState(element: Element, props: Object) {
export function updateWrapper(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
const value = getToStringValue(props.value);
const defaultValue = getToStringValue(props.defaultValue);
if (value != null) {
// Cast `value` to a string to ensure the value is set correctly. While
// browsers typically do this as necessary, jsdom doesn't.
Expand All @@ -136,12 +137,12 @@ export function updateWrapper(element: Element, props: Object) {
if (newValue !== node.value) {
node.value = newValue;
}
if (props.defaultValue == null) {
if (props.defaultValue == null && node.defaultValue !== newValue) {
node.defaultValue = newValue;
}
}
if (props.defaultValue != null) {
node.defaultValue = toString(getToStringValue(props.defaultValue));
if (defaultValue != null) {
node.defaultValue = toString(defaultValue);
}
}

Expand Down

0 comments on commit d92114b

Please sign in to comment.