diff --git a/packages/docs/src/components/TextInput/TextInput.stories.mdx b/packages/docs/src/components/TextInput/TextInput.stories.mdx
index 7ac57051..d0ff1118 100644
--- a/packages/docs/src/components/TextInput/TextInput.stories.mdx
+++ b/packages/docs/src/components/TextInput/TextInput.stories.mdx
@@ -209,6 +209,12 @@ called with `{ nativeEvent: { selection: { start, end } } }`.
+
+
+
+
+
+
### onSubmitEditing
Callback that is called when the keyboard's submit button is pressed. When
diff --git a/packages/docs/src/components/TextInput/examples/OnSelectionChange.js b/packages/docs/src/components/TextInput/examples/OnSelectionChange.js
index 82b4bbd1..4a4957de 100644
--- a/packages/docs/src/components/TextInput/examples/OnSelectionChange.js
+++ b/packages/docs/src/components/TextInput/examples/OnSelectionChange.js
@@ -2,106 +2,27 @@
* @noflow
*/
-import React from 'react';
+import React, { useState } from 'react';
+import { View, Text, TextInput } from 'react-native';
import { styles } from '../helpers';
-import { Text, TextInput, View } from 'react-native';
-type SelectionExampleState = {
- selection: {
- start: number,
- end?: number
- },
- value: string
-};
+function OnSelectionChange() {
+ const [text, setText] = useState('');
+ const [selection, setSelection] = useState({ start: 0, end: 0 });
-class OnSelectionChangeExample extends React.Component {
- state: SelectionExampleState;
-
- _textInput: any;
-
- constructor(props) {
- super(props);
- this.state = {
- selection: { start: 0, end: 0 },
- value: props.value
- };
- }
-
- onSelectionChange = ({ nativeEvent: { selection } }) => {
- this.setState({ selection });
- };
-
- onChangeText = value => {
- this.setState({ value });
- };
-
- getRandomPosition() {
- const length = this.state.value.length;
- return Math.round(Math.random() * length);
- }
-
- select = (start, end) => () => {
- this._textInput.focus();
- this.setState({ selection: { start, end } });
- };
-
- selectRandom = () => {
- const positions = [this.getRandomPosition(), this.getRandomPosition()].sort();
- this.select(...positions)();
- };
-
- placeAt = position => () => {
- this.select(position, position)();
- };
-
- placeAtRandom = () => {
- this.placeAt(this.getRandomPosition())();
- };
-
- setRef = textInput => {
- this._textInput = textInput;
- };
-
- render() {
- const length = this.state.value.length;
-
- return (
-
-
-
- selection = {JSON.stringify(this.state.selection)}
- Place at Start (0, 0)
-
- Place at End ({length}, {length})
-
- Place at Random
- Select All
- Select Random
-
-
- );
- }
+ return (
+
+ {
+ setSelection(event.nativeEvent.selection);
+ }}
+ style={styles.textinput}
+ value={text}
+ />
+ {JSON.stringify(selection)}
+
+ );
}
-const TextInputOnSelectionChangeExample = () => (
-
-
-
-
-);
-
-export default function OnSelectionChange() {
- return ;
-}
+export default OnSelectionChange;
diff --git a/packages/docs/src/components/TextInput/examples/OnSelectionChangeControlled.js b/packages/docs/src/components/TextInput/examples/OnSelectionChangeControlled.js
new file mode 100644
index 00000000..82b4bbd1
--- /dev/null
+++ b/packages/docs/src/components/TextInput/examples/OnSelectionChangeControlled.js
@@ -0,0 +1,107 @@
+/**
+ * @noflow
+ */
+
+import React from 'react';
+import { styles } from '../helpers';
+import { Text, TextInput, View } from 'react-native';
+
+type SelectionExampleState = {
+ selection: {
+ start: number,
+ end?: number
+ },
+ value: string
+};
+
+class OnSelectionChangeExample extends React.Component {
+ state: SelectionExampleState;
+
+ _textInput: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ selection: { start: 0, end: 0 },
+ value: props.value
+ };
+ }
+
+ onSelectionChange = ({ nativeEvent: { selection } }) => {
+ this.setState({ selection });
+ };
+
+ onChangeText = value => {
+ this.setState({ value });
+ };
+
+ getRandomPosition() {
+ const length = this.state.value.length;
+ return Math.round(Math.random() * length);
+ }
+
+ select = (start, end) => () => {
+ this._textInput.focus();
+ this.setState({ selection: { start, end } });
+ };
+
+ selectRandom = () => {
+ const positions = [this.getRandomPosition(), this.getRandomPosition()].sort();
+ this.select(...positions)();
+ };
+
+ placeAt = position => () => {
+ this.select(position, position)();
+ };
+
+ placeAtRandom = () => {
+ this.placeAt(this.getRandomPosition())();
+ };
+
+ setRef = textInput => {
+ this._textInput = textInput;
+ };
+
+ render() {
+ const length = this.state.value.length;
+
+ return (
+
+
+
+ selection = {JSON.stringify(this.state.selection)}
+ Place at Start (0, 0)
+
+ Place at End ({length}, {length})
+
+ Place at Random
+ Select All
+ Select Random
+
+
+ );
+ }
+}
+
+const TextInputOnSelectionChangeExample = () => (
+
+
+
+
+);
+
+export default function OnSelectionChange() {
+ return ;
+}
diff --git a/packages/docs/src/components/TextInput/examples/index.js b/packages/docs/src/components/TextInput/examples/index.js
index f71a70fe..176dcd49 100644
--- a/packages/docs/src/components/TextInput/examples/index.js
+++ b/packages/docs/src/components/TextInput/examples/index.js
@@ -9,6 +9,7 @@ export { default as maxLength } from './MaxLength';
export { default as multiline } from './Multiline';
export { default as numberOfLines } from './NumberOfLines';
export { default as onSelectionChange } from './OnSelectionChange';
+export { default as onSelectionChangeControlled } from './OnSelectionChangeControlled';
export { default as placeholder } from './Placeholder';
export { default as placeholderTextColor } from './PlaceholderTextColor';
export { default as secureTextEntry } from './SecureTextEntry';
diff --git a/packages/react-native-web/src/exports/TextInput/index.js b/packages/react-native-web/src/exports/TextInput/index.js
index 5cfd039f..a134eae5 100644
--- a/packages/react-native-web/src/exports/TextInput/index.js
+++ b/packages/react-native-web/src/exports/TextInput/index.js
@@ -22,19 +22,14 @@ import useResponderEvents from '../../hooks/useResponderEvents';
import StyleSheet from '../StyleSheet';
import TextInputState from '../../modules/TextInputState';
-const emptyObject = {};
-
/**
* Determines whether a 'selection' prop differs from a node's existing
* selection state.
*/
const isSelectionStale = (node, selection) => {
- if (node != null && selection != null && selection.start != null) {
- const { selectionEnd, selectionStart } = node;
- const { start, end } = selection;
- return start !== selectionStart || end !== selectionEnd;
- }
- return false;
+ const { selectionEnd, selectionStart } = node;
+ const { start, end } = selection;
+ return start !== selectionStart || end !== selectionEnd;
};
/**
@@ -42,7 +37,7 @@ const isSelectionStale = (node, selection) => {
* error.
*/
const setSelection = (node, selection) => {
- if (node != null && selection != null && isSelectionStale(node, selection)) {
+ if (isSelectionStale(node, selection)) {
const { start, end } = selection;
try {
node.setSelectionRange(start, end || start);
@@ -155,7 +150,7 @@ const TextInput = forwardRef((props, forwardedRef) => {
placeholderTextColor,
returnKeyType,
secureTextEntry = false,
- selection = emptyObject,
+ selection,
selectTextOnFocus,
spellCheck
} = props;
@@ -251,7 +246,6 @@ const TextInput = forwardRef((props, forwardedRef) => {
if (onChangeText) {
onChangeText(text);
}
- handleSelectionChange(e);
}
function handleFocus(e) {
@@ -312,22 +306,22 @@ const TextInput = forwardRef((props, forwardedRef) => {
if (onSelectionChange) {
try {
const node = e.target;
- if (isSelectionStale(node, selection)) {
- const { selectionStart, selectionEnd } = node;
- e.nativeEvent.selection = {
- start: selectionStart,
- end: selectionEnd
- };
- e.nativeEvent.text = e.target.value;
- onSelectionChange(e);
- }
+ const { selectionStart, selectionEnd } = node;
+ e.nativeEvent.selection = {
+ start: selectionStart,
+ end: selectionEnd
+ };
+ e.nativeEvent.text = e.target.value;
+ onSelectionChange(e);
} catch (e) {}
}
}
useLayoutEffect(() => {
const node = hostRef.current;
- setSelection(node, selection);
+ if (node != null && selection != null) {
+ setSelection(node, selection);
+ }
if (document.activeElement === node) {
TextInputState._currentlyFocusedNode = node;
}