From 5e41208b78c7ed69308985f9f915c5e1f7db4684 Mon Sep 17 00:00:00 2001 From: Pedro Guerreiro Date: Fri, 28 Jul 2023 19:01:25 +0100 Subject: [PATCH] [fix] TextInput cursor position with secureTextEntry On web, the cursor jumps to the start of the input when secureTextEntry is toggled. Preserve and restore previous selection after secureTextEntry is toggled. Close #2576 --- .../src/exports/TextInput/index.js | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/react-native-web/src/exports/TextInput/index.js b/packages/react-native-web/src/exports/TextInput/index.js index 5cfd6bad..285cb2d2 100644 --- a/packages/react-native-web/src/exports/TextInput/index.js +++ b/packages/react-native-web/src/exports/TextInput/index.js @@ -193,6 +193,15 @@ const TextInput: React.AbstractComponent< const dimensions = React.useRef({ height: null, width: null }); const hostRef = React.useRef(null); + const prevSelection = React.useRef(null); + const prevSecureTextEntry = React.useRef(false); + + React.useEffect(() => { + if (hostRef.current && prevSelection.current) { + setSelection(hostRef.current, prevSelection.current); + } + prevSecureTextEntry.current = secureTextEntry; + }, [secureTextEntry]); const handleContentSizeChange = React.useCallback( (hostNode) => { @@ -324,18 +333,21 @@ const TextInput: React.AbstractComponent< } function handleSelectionChange(e) { - if (onSelectionChange) { - try { - const node = e.target; - const { selectionStart, selectionEnd } = node; - e.nativeEvent.selection = { - start: selectionStart, - end: selectionEnd - }; + try { + const { selectionStart, selectionEnd } = e.target; + const selection = { + start: selectionStart, + end: selectionEnd + }; + if (onSelectionChange) { + e.nativeEvent.selection = selection; e.nativeEvent.text = e.target.value; onSelectionChange(e); - } catch (e) {} - } + } + if (prevSecureTextEntry.current === secureTextEntry) { + prevSelection.current = selection; + } + } catch (e) {} } useLayoutEffect(() => {