diff --git a/packages/react-dom-bindings/src/client/ReactDOMInput.js b/packages/react-dom-bindings/src/client/ReactDOMInput.js
index 0708b984f7c95..fcede97885728 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMInput.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMInput.js
@@ -84,7 +84,7 @@ export function validateInputProps(element: Element, props: Object) {
export function updateInputChecked(element: Element, props: Object) {
const node: HTMLInputElement = (element: any);
const checked = props.checked;
- if (checked != null && node.checked !== !!checked) {
+ if (checked != null) {
node.checked = checked;
}
}
diff --git a/packages/react-dom-bindings/src/client/ReactDOMTextarea.js b/packages/react-dom-bindings/src/client/ReactDOMTextarea.js
index c9862c9b00bef..544cee9952be9 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMTextarea.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMTextarea.js
@@ -61,6 +61,12 @@ export function validateTextareaProps(element: Element, props: Object) {
export function updateTextarea(element: Element, props: Object) {
const node: HTMLTextAreaElement = (element: any);
const value = getToStringValue(props.value);
+ const defaultValue = getToStringValue(props.defaultValue);
+ if (defaultValue != null) {
+ node.defaultValue = toString(defaultValue);
+ } else {
+ node.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.
@@ -70,19 +76,10 @@ export function updateTextarea(element: Element, props: Object) {
node.value = newValue;
}
// TOOO: This should respect disableInputAttributeSyncing flag.
- if (props.defaultValue == null) {
- if (node.defaultValue !== newValue) {
- node.defaultValue = newValue;
- }
- return;
+ if (props.defaultValue == null && node.defaultValue !== newValue) {
+ node.defaultValue = newValue;
}
}
- const defaultValue = getToStringValue(props.defaultValue);
- if (defaultValue != null) {
- node.defaultValue = toString(defaultValue);
- } else {
- node.defaultValue = '';
- }
}
export function initTextarea(element: Element, props: Object) {
diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
index c2dd984823ed1..b8c91fb86e18b 100644
--- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
@@ -1043,63 +1043,6 @@ describe('ReactDOMComponent', () => {
expect(nodeValueSetter).toHaveBeenCalledTimes(2);
});
- it('should not incur unnecessary DOM mutations for controlled string properties', () => {
- function onChange() {}
- const container = document.createElement('div');
- ReactDOM.render(, container);
-
- const node = container.firstChild;
-
- let nodeValue = '';
- const nodeValueSetter = jest.fn();
- Object.defineProperty(node, 'value', {
- get: function () {
- return nodeValue;
- },
- set: nodeValueSetter.mockImplementation(function (newValue) {
- nodeValue = newValue;
- }),
- });
-
- ReactDOM.render(, container);
- expect(nodeValueSetter).toHaveBeenCalledTimes(1);
-
- ReactDOM.render(
- ,
- container,
- );
- expect(nodeValueSetter).toHaveBeenCalledTimes(1);
-
- expect(() => {
- ReactDOM.render(, container);
- }).toErrorDev(
- 'A component is changing a controlled input to be uncontrolled. This is likely caused by ' +
- 'the value changing from a defined to undefined, which should not happen. Decide between ' +
- 'using a controlled or uncontrolled input element for the lifetime of the component.',
- );
- expect(nodeValueSetter).toHaveBeenCalledTimes(1);
-
- expect(() => {
- ReactDOM.render(, container);
- }).toErrorDev(
- 'value` prop on `input` should not be null. Consider using an empty string to clear the ' +
- 'component or `undefined` for uncontrolled components.',
- );
- expect(nodeValueSetter).toHaveBeenCalledTimes(1);
-
- expect(() => {
- ReactDOM.render(, container);
- }).toErrorDev(
- ' A component is changing an uncontrolled input to be controlled. This is likely caused by ' +
- 'the value changing from undefined to a defined value, which should not happen. Decide between ' +
- 'using a controlled or uncontrolled input element for the lifetime of the component.',
- );
- expect(nodeValueSetter).toHaveBeenCalledTimes(2);
-
- ReactDOM.render(, container);
- expect(nodeValueSetter).toHaveBeenCalledTimes(2);
- });
-
it('should not incur unnecessary DOM mutations for boolean properties', () => {
const container = document.createElement('div');
function onChange() {
@@ -1123,12 +1066,7 @@ describe('ReactDOMComponent', () => {
});
ReactDOM.render(
- ,
+ ,
container,
);
expect(nodeValueSetter).toHaveBeenCalledTimes(0);
@@ -1156,13 +1094,15 @@ describe('ReactDOMComponent', () => {
'using a controlled or uncontrolled input element for the lifetime of the component.',
);
- expect(nodeValueSetter).toHaveBeenCalledTimes(2);
+ // TODO: Non-null values are updated twice on inputs. This is should ideally be fixed.
+ expect(nodeValueSetter).toHaveBeenCalledTimes(3);
ReactDOM.render(
,
container,
);
- expect(nodeValueSetter).toHaveBeenCalledTimes(3);
+ // TODO: Non-null values are updated twice on inputs. This is should ideally be fixed.
+ expect(nodeValueSetter).toHaveBeenCalledTimes(5);
});
it('should ignore attribute list for elements with the "is" attribute', () => {
diff --git a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
index 347942234063d..396eef8d6d34e 100644
--- a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js
@@ -603,7 +603,6 @@ describe('ReactDOMTextarea', () => {
ref={n => (node = n)}
value="foo"
onChange={emptyFunction}
- data-count={this.state.count}
/>
);