Skip to content

Commit b4993d7

Browse files
committed
Do not set selection when prior selection is undefined (#12062)
`restoreSelection` did not account for input elements that have changed type after the commit phase. The new `text` input supported selection but the old `email` did not and `setSelection` was incorrectly trying to restore `null` selection state. We also extend input type check in selection capabilities to cover cases where input type is `search`, `tel`, `url`, or `password`.
1 parent 6bf2797 commit b4993d7

File tree

4 files changed

+173
-116
lines changed

4 files changed

+173
-116
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Fixture from '../../Fixture';
2+
3+
const React = window.React;
4+
5+
class ReplaceEmailInput extends React.Component {
6+
state = {
7+
formSubmitted: false,
8+
};
9+
10+
render() {
11+
return (
12+
<Fixture>
13+
<form
14+
className="control-box"
15+
onSubmit={event => {
16+
event.preventDefault();
17+
this.setState({formSubmitted: true});
18+
}}>
19+
<fieldset>
20+
<legend>Email</legend>
21+
{!this.state.formSubmitted ? (
22+
<input type="email" />
23+
) : (
24+
<input type="text" disabled={true} />
25+
)}
26+
</fieldset>
27+
</form>
28+
</Fixture>
29+
);
30+
}
31+
}
32+
33+
export default ReplaceEmailInput;

fixtures/dom/src/components/fixtures/text-inputs/index.js

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Fixture from '../../Fixture';
22
import FixtureSet from '../../FixtureSet';
33
import TestCase from '../../TestCase';
44
import InputTestCase from './InputTestCase';
5+
import ReplaceEmailInput from './ReplaceEmailInput';
56

67
const React = window.React;
78

@@ -110,6 +111,21 @@ class TextInputFixtures extends React.Component {
110111
<InputTestCase type="url" defaultValue="" />
111112
</TestCase>
112113

114+
<TestCase
115+
title="Replacing email input with text disabled input"
116+
relatedIssues="12062">
117+
<TestCase.Steps>
118+
<li>Type "test@test.com"</li>
119+
<li>Press enter</li>
120+
</TestCase.Steps>
121+
122+
<TestCase.ExpectedResult>
123+
There should be no selection-related error in the console.
124+
</TestCase.ExpectedResult>
125+
126+
<ReplaceEmailInput />
127+
</TestCase>
128+
113129
<TestCase title="All inputs" description="General test of all inputs">
114130
<InputTestCase type="text" defaultValue="Text" />
115131
<InputTestCase type="email" defaultValue="user@example.com" />

packages/react-dom/src/client/ReactInputSelection.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ export function hasSelectionCapabilities(elem) {
2626
const nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
2727
return (
2828
nodeName &&
29-
((nodeName === 'input' && elem.type === 'text') ||
29+
((nodeName === 'input' &&
30+
(elem.type === 'text' ||
31+
elem.type === 'search' ||
32+
elem.type === 'tel' ||
33+
elem.type === 'url' ||
34+
elem.type === 'password')) ||
3035
nodeName === 'textarea' ||
3136
elem.contentEditable === 'true')
3237
);
@@ -52,7 +57,10 @@ export function restoreSelection(priorSelectionInformation) {
5257
const priorFocusedElem = priorSelectionInformation.focusedElem;
5358
const priorSelectionRange = priorSelectionInformation.selectionRange;
5459
if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
55-
if (hasSelectionCapabilities(priorFocusedElem)) {
60+
if (
61+
priorSelectionRange !== null &&
62+
hasSelectionCapabilities(priorFocusedElem)
63+
) {
5664
setSelection(priorFocusedElem, priorSelectionRange);
5765
}
5866

0 commit comments

Comments
 (0)