+
- let onChange = e => {
- let value = e.target.value;
- if (type === 'number') {
- value = value === '' ? '' : parseFloat(value, 10) || 0;
- }
- this.setState({
- [type] : value,
- });
- };
+
+ The text field's value should not update.
+
- let state = this.state[type] || '';
+
+
+
- return (
-
-
-
- → {JSON.stringify(state)}
-
- );
- }
+
+
+
- renderUncontrolled = (type) => {
- let id = `uncontrolled_${type}`;
- return (
-
-
-
-
- );
- }
+
+ This issue was first introduced when we added extra logic
+ to number inputs to prevent unexpected behavior in Chrome
+ and Safari (see the number input test case).
+
+
- render() {
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
- let types = [
- 'text', 'email', 'number', 'url', 'tel',
- 'color', 'date', 'datetime-local',
- 'time', 'month', 'week', 'range', 'password',
- ];
- return (
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
}
diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt
index 02bc0a8cb8573..01cba63cf1284 100644
--- a/scripts/fiber/tests-passing.txt
+++ b/scripts/fiber/tests-passing.txt
@@ -1452,6 +1452,9 @@ src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
* should properly control a value even if no event listener exists
* should control a value in reentrant events
* should control values in reentrant events with different targets
+* does change the number 2 to "2.0" with no change handler
+* does change the string "2" to "2.0" with no change handler
+* changes the number 2 to "2.0" using a change handler
* should display `defaultValue` of number 0
* only assigns defaultValue if it changes
* should display "true" for `defaultValue` of `true`
@@ -1671,6 +1674,7 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
* can deprioritize a tree from without dropping work
* can resume work in a subtree even when a parent bails out
* can resume work in a bailed subtree within one pass
+* can resume mounting a class component
* can reuse work done after being preempted
* can reuse work that began but did not complete, after being preempted
* can reuse work if shouldComponentUpdate is false, after being preempted
diff --git a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
index ebc9812077ea2..e93b057154cde 100644
--- a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
+++ b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
@@ -210,7 +210,7 @@ var ReactDOMInput = {
node.value = '' + value;
}
// eslint-disable-next-line
- } else if (value != node.value) {
+ } else {
// 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;
diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
index 16b2fba74814a..87a4d6b000e16 100644
--- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
+++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
@@ -179,6 +179,60 @@ describe('ReactDOMInput', () => {
document.body.removeChild(container);
});
+ describe('switching text inputs between numeric and string numbers', () => {
+ it('does change the number 2 to "2.0" with no change handler', () => {
+ var stub = ;
+ stub = ReactTestUtils.renderIntoDocument(stub);
+ var node = ReactDOM.findDOMNode(stub);
+
+ node.value = '2.0';
+
+ ReactTestUtils.Simulate.change(stub);
+
+ expect(node.getAttribute('value')).toBe('2');
+ expect(node.value).toBe('2');
+ });
+
+ it('does change the string "2" to "2.0" with no change handler', () => {
+ var stub = ;
+ stub = ReactTestUtils.renderIntoDocument(stub);
+ var node = ReactDOM.findDOMNode(stub);
+
+ node.value = '2.0';
+
+ ReactTestUtils.Simulate.change(stub);
+
+ expect(node.getAttribute('value')).toBe('2');
+ expect(node.value).toBe('2');
+ });
+
+ it('changes the number 2 to "2.0" using a change handler', () => {
+ class Stub extends React.Component {
+ state = {
+ value: 2,
+ };
+ onChange = event => {
+ this.setState({value: event.target.value});
+ };
+ render() {
+ const {value} = this.state;
+
+ return ;
+ }
+ }
+
+ var stub = ReactTestUtils.renderIntoDocument();
+ var node = ReactDOM.findDOMNode(stub);
+
+ node.value = '2.0';
+
+ ReactTestUtils.Simulate.change(node);
+
+ expect(node.getAttribute('value')).toBe('2.0');
+ expect(node.value).toBe('2.0');
+ });
+ });
+
it('should display `defaultValue` of number 0', () => {
var stub = ;
stub = ReactTestUtils.renderIntoDocument(stub);
@@ -411,10 +465,10 @@ describe('ReactDOMInput', () => {
});
ReactDOM.render(, container);
- expect(nodeValueSetter.mock.calls.length).toBe(0);
+ expect(nodeValueSetter.mock.calls.length).toBe(1);
ReactDOM.render(, container);
- expect(nodeValueSetter.mock.calls.length).toBe(1);
+ expect(nodeValueSetter.mock.calls.length).toBe(2);
});
it('should properly control a value of number `0`', () => {
@@ -434,7 +488,7 @@ describe('ReactDOMInput', () => {
node.value = '0.0';
ReactTestUtils.Simulate.change(node, {target: {value: '0.0'}});
- expect(node.value).toBe('0.0');
+ expect(node.value).toBe('0');
});
it('should properly control 0.0 for a number input', () => {
diff --git a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
index 15c98554b4578..1fcea21865a16 100644
--- a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
+++ b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
@@ -202,7 +202,7 @@ var ReactDOMInput = {
node.value = '' + value;
}
// eslint-disable-next-line
- } else if (value != node.value) {
+ } else {
// 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;
From 3e1a7681273ef00e2e2209ba0d85e93fd28c5275 Mon Sep 17 00:00:00 2001
From: Nathan Hunzaker
Date: Tue, 2 May 2017 19:59:15 -0400
Subject: [PATCH 2/3] Use strict equality as a guard before assigning
input.value
This commit adds back the guard around assigning the value property to
an input, however it does it using a strict equals. This prevents
validated inputs, like emails and urls from losing the cursor
position.
It also adds associated test fixtures.
---
.../components/fixtures/text-inputs/index.js | 28 +++++++++++++++++++
.../dom/fiber/wrappers/ReactDOMFiberInput.js | 3 +-
.../stack/client/wrappers/ReactDOMInput.js | 3 +-
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/fixtures/dom/src/components/fixtures/text-inputs/index.js b/fixtures/dom/src/components/fixtures/text-inputs/index.js
index bc40fa67d9182..6d6ee9a687db6 100644
--- a/fixtures/dom/src/components/fixtures/text-inputs/index.js
+++ b/fixtures/dom/src/components/fixtures/text-inputs/index.js
@@ -43,6 +43,34 @@ class TextInputFixtures extends React.Component {
+
+
+
Type "user@example.com"
+
Select "@"
+
Type ".", to replace "@" with a period
+
+
+
+ The text field's cursor should not jump to the end.
+
+
+
+
+
+
+
+
Type "http://www.example.com"
+
Select "www."
+
Press backspace/delete
+
+
+
+ The text field's cursor should not jump to the end.
+
+
+
+
+
diff --git a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
index e93b057154cde..41de9687e429d 100644
--- a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
+++ b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js
@@ -209,8 +209,7 @@ var ReactDOMInput = {
// browsers typically do this as necessary, jsdom doesn't.
node.value = '' + value;
}
- // eslint-disable-next-line
- } else {
+ } else if (node.value !== value) {
// 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;
diff --git a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
index 1fcea21865a16..b05ca82b352db 100644
--- a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
+++ b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js
@@ -201,8 +201,7 @@ var ReactDOMInput = {
// browsers typically do this as necessary, jsdom doesn't.
node.value = '' + value;
}
- // eslint-disable-next-line
- } else {
+ } else if (node.value !== value) {
// 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;
From d421181b86cab854b27fe182c15c6cad528a67c4 Mon Sep 17 00:00:00 2001
From: Nathan Hunzaker
Date: Tue, 2 May 2017 20:09:42 -0400
Subject: [PATCH 3/3] Add copy command after build for interup with surge.sh
---
fixtures/dom/package.json | 2 +-
.../dom/shared/wrappers/__tests__/ReactDOMInput-test.js | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fixtures/dom/package.json b/fixtures/dom/package.json
index 214de66fb73a6..d27936a4da275 100644
--- a/fixtures/dom/package.json
+++ b/fixtures/dom/package.json
@@ -16,7 +16,7 @@
"scripts": {
"start": "react-scripts start",
"prestart": "cp ../../build/dist/{react,react-dom}.development.js public/",
- "build": "react-scripts build",
+ "build": "react-scripts build && cp build/index.html build/200.html",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
index 87a4d6b000e16..19a38b9e182f5 100644
--- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
+++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js
@@ -465,10 +465,10 @@ describe('ReactDOMInput', () => {
});
ReactDOM.render(, container);
- expect(nodeValueSetter.mock.calls.length).toBe(1);
+ expect(nodeValueSetter.mock.calls.length).toBe(0);
ReactDOM.render(, container);
- expect(nodeValueSetter.mock.calls.length).toBe(2);
+ expect(nodeValueSetter.mock.calls.length).toBe(1);
});
it('should properly control a value of number `0`', () => {