Skip to content

Synchronizing selection of TextInput from onSelectionChange causes cursor to jump #50641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
z4pf1sh opened this issue Apr 11, 2025 · 3 comments
Closed
Labels
Component: TextInput Related to the TextInput component. Needs: Triage 🔍

Comments

@z4pf1sh
Copy link

z4pf1sh commented Apr 11, 2025

Description

We're using React Native 0.77.2, and are trying to synchronize onSelectionChange event's data to a React State, bound to TextInput's selection property. With our implementation, when the first letter is typed into the TextInput, the cursor jumps to the beginning of the TextInput. Subsequent inputs are fine without any problem.

Steps to reproduce

  1. Create a new RN project with npx @react-native-community/cli@latest init AwesomeProject --version 0.77.2
  2. Initialize the project normally
  3. Enter ios folder, run pod install, as one normally would
  4. Open AwesomeProject.xcworkspace
  5. Run yarn run start in the root folder to start Metro server
  6. Run the Xcode project, allowing the app to connect to Metro
  7. Select the TextInput widget and type anything into it
  8. Observe the cursor "remaining" at the start of the TextInput

React Native Version

0.77.2

Affected Platforms

Runtime - iOS

Output of npx @react-native-community/cli info

info Fetching system and libraries information...
System:
  OS: macOS 15.1.1
  CPU: (12) arm64 Apple M3 Pro
  Memory: 176.25 MB / 18.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.17.0
    path: ~/.nvm/versions/node/v20.17.0/bin/node
  Yarn:
    version: 1.22.22
    path: ~/Library/pnpm/yarn
  npm:
    version: 10.9.2
    path: ~/.nvm/versions/node/v20.17.0/bin/npm
  Watchman:
    version: 2025.03.10.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/test/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.2
      - iOS 18.2
      - macOS 15.2
      - tvOS 18.2
      - visionOS 2.2
      - watchOS 11.2
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.23726.103.2422.12816248
  Xcode:
    version: 16.2/16C5032a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 11.0.26
    path: /usr/bin/javac
  Ruby:
    version: 2.7.7
    path: /Users/test/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.77.2
    wanted: 0.77.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

info React Native v0.79.0 is now available (your project is running on v0.77.2).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.79.0
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.77.2&to=0.79.0
info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos".

Stacktrace or Logs

(not available because it is not a crash)

Reproducer

https://github.com/z4pf1sh/repro-rn-textinput

Screenshots and Videos

Screen.Recording.2025-04-11.at.15.48.32.mov
@react-native-bot react-native-bot added the Component: TextInput Related to the TextInput component. label Apr 11, 2025
@z4pf1sh
Copy link
Author

z4pf1sh commented Apr 11, 2025

FYI: it works fine for us with RN 0.74.3. This may be a regression associated with recent revamps of TextInput.

@devanshsaini11
Copy link
Collaborator

Hi @z4pf1sh , could you please verify this on the latest React Native version 0.79.x?
Thanks!

@z4pf1sh
Copy link
Author

z4pf1sh commented Apr 14, 2025

Hi, @devanshsaini11, I have tested with RN 0.79.0 and am sorry to report that this issue still persists in RN 0.79.0.

However I do notice a community patch in this thread. I've cherry-picked the patch and it fixed the issue. Maybe consider taking a look into it? ;)

fabriziocucci pushed a commit that referenced this issue Apr 14, 2025
Summary:
Avoid incorrectly updating caret position

Pull Request resolved: #50641

The caret position is updated incorrectly when a user is first typing if an zero-length selection is set.

[IOS] [CHANGED] - Typing into TextInput now will not cause the caret position to update to the beginning when a zero-length selection is set.

Pull Request resolved: #50680

Test Plan:
Tested with the following code(a simplified version from the code in #50641)
```js
const [selection, setSelection] = useState({start: -1, end: -1});
const onSelectionChange = (
      evt: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
    ) => {
      const {selection} = evt.nativeEvent;
      const {start, end} = selection;
      console.log('selection change: ', start, end);
      setSelection(selection);
};
return (
  <View style={{ position: 'absolute', top: 50, left: 30 }}>
    <TextInput
      placeholder="test"
      selection={selection}
      onSelectionChange={onSelectionChange}
    />
  </View>
);
```
When using the main branch, the caret position will jump back to the beginning after the first typing.
It works fine after applying this commit.

Reviewed By: fabriziocucci

Differential Revision: D72957245

Pulled By: cipolleschi

fbshipit-source-id: 3586797332b35e86b17f386a35e7d192ff758f7e
uffoltzl pushed a commit to uffoltzl/react-native that referenced this issue Apr 18, 2025
Summary:
Avoid incorrectly updating caret position

Pull Request resolved: facebook#50641

The caret position is updated incorrectly when a user is first typing if an zero-length selection is set.

## Changelog:
[IOS] [CHANGED] - Typing into TextInput now will not cause the caret position to update to the beginning when a zero-length selection is set.

Pull Request resolved: facebook#50680

Test Plan:
Tested with the following code(a simplified version from the code in facebook#50641)
```js
const [selection, setSelection] = useState({start: -1, end: -1});
const onSelectionChange = (
      evt: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
    ) => {
      const {selection} = evt.nativeEvent;
      const {start, end} = selection;
      console.log('selection change: ', start, end);
      setSelection(selection);
};
return (
  <View style={{ position: 'absolute', top: 50, left: 30 }}>
    <TextInput
      placeholder="test"
      selection={selection}
      onSelectionChange={onSelectionChange}
    />
  </View>
);
```
When using the main branch, the caret position will jump back to the beginning after the first typing.
It works fine after applying this commit.

Reviewed By: fabriziocucci

Differential Revision: D72957245

Pulled By: cipolleschi

fbshipit-source-id: 3586797332b35e86b17f386a35e7d192ff758f7e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: TextInput Related to the TextInput component. Needs: Triage 🔍
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants