react-native icon indicating copy to clipboard operation
react-native copied to clipboard

TextInput > iOS > selectTextOnFocus not working as expected

Open AlirezaHadjar opened this issue 1 year ago • 7 comments

Description

I created a fresh project using the npx react-native@latest init textinputBug and added a simple text input.

 <TextInput
          value="test"
          style={{marginBottom: 20, backgroundColor: 'grey', padding: 10}}
          selectTextOnFocus
        />

Noticed 2 weird behaviors on iOS. I tested on both iOS 16.4 and 17.2.

  • The first issue is that if you press on any words of a non-focused text input, the text will be selected on the 16.4 but not on the 17.2.
  • The second issue is that if you press on the text input area that doesn't have any text, the text will not be selected on either of the devices. I'm unsure if this is a bug or a default behavior of text inputs on iOS. (the same action selects the whole text on Android)

Please watch the video for more information and let me know if you need more info

Steps to reproduce

  1. Initialized a fresh project using npx react-native@latest init textinputBug
  2. Added a text input with the mentioned props
  3. Noticed weird behaviors

React Native Version

0.73.1

Affected Platforms

Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 14.2
  CPU: (8) arm64 Apple M1 Pro
  Memory: 105.28 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.18.0
    path: ~/.nvm/versions/node/v18.18.0/bin/node
  Yarn:
    version: 1.22.19
    path: /usr/local/bin/yarn
  npm:
    version: 9.8.1
    path: ~/.nvm/versions/node/v18.18.0/bin/npm
  Watchman:
    version: 2023.09.04.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.13.0
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.2
      - iOS 17.2
      - macOS 14.2
      - tvOS 17.2
      - watchOS 10.2
  Android SDK:
    API Levels:
      - "27"
      - "28"
      - "29"
      - "30"
      - "31"
      - "33"
      - "33"
      - "34"
    Build Tools:
      - 30.0.3
      - 33.0.0
      - 33.0.1
      - 33.0.2
      - 34.0.0
    System Images:
      - android-28 | Google ARM64-V8a Play ARM 64 v8a
      - android-33 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2022.3 AI-223.8836.35.2231.10406996
  Xcode:
    version: 15.1/15C65
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.8.1
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.73.1
    wanted: 0.73.1
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

There's not runtime error. It's a UI bug

Reproducer

https://github.com/AlirezaHadjar/textinputBug

Screenshots and Videos

https://github.com/facebook/react-native/assets/57192409/acbb404f-573c-4292-85b8-8ea049118fcd

AlirezaHadjar avatar Dec 19 '23 09:12 AlirezaHadjar

Related to this issue: https://github.com/facebook/react-native/issues/30585

This is still a bug, selectTextOnFocus does not work for me either on iOS as expected (I'm on react-native 0.72.6).

A working temporary solution is found here: https://github.com/facebook/react-native/issues/30585#issuecomment-1330928411 (thanks @pascallapointe)

<TextInput
  value={value}
  onFocus={e => 
       // Workaround for selectTextOnFocus={true} not working
       e.currentTarget.setNativeProps({
           selection: { start: 0, end: value?.toString().length },
       });
  }
  ...
/>

Setting multiline to true also works, but this does not fit my use-case since then returnKeyType='done' enters a new line instead of toggling the keyboard.

bennettfrazier avatar Jan 25 '24 23:01 bennettfrazier

I'm also having this issue and it seems to work intermittently in no predictable way

erickreutz avatar Feb 07 '24 13:02 erickreutz

Happening for me too.

edwinvrgs avatar Apr 09 '24 21:04 edwinvrgs

Happening to me too. I managed to fix it by also including the selection prop, seems they are linked in some way, while not being explained in the documentation?

Rednegniw avatar Apr 24 '24 09:04 Rednegniw

Happening to me too. I managed to fix it by also including the selection prop, seems they are linked in some way, while not being explained in the documentation?

This option works, but is not very good from a UX point of view, because the text will be highlighted every time (also when editing).

My temporal suggestion it's using ref for set selection on focus.


const ref = useRef(null)
const [value, setValue] = useState('');

const onFocus = () => {
 input.current?.setSelection(0, value.length);
}

return <TextInput value={value} onChangeText={setValue} ref={ref} onFocus={onFocus} />

teivienn avatar Apr 25 '24 08:04 teivienn

I'm hitting this too. I think it's a bug. Does anyone have a burning desire to dig into the source code and figure out what's going on?

gaearon avatar Apr 28 '24 21:04 gaearon

I briefly investigated this and seem to have found the cause of the problem and a potential fix. Opened a PR here. Hopefully if it isn't the right fix it at least points in the right direction for someone to pick it up (especially since it also affects Fabric!) https://github.com/facebook/react-native/pull/44307

Right now, the underlying native code selects the text like so in non-fabric:

- (void)textInputDidBeginEditing
{
  // Removed some other code for clarity

  if (_selectTextOnFocus) {
    [self.backedTextInputView selectAll:nil];
  }

  [_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
                                 reactTag:self.reactTag
                                     text:[self.backedTextInputView.attributedText.string copy]
                                      key:nil
                               eventCount:_nativeEventCount];
}

This seems logical at first glance, and it actually is highlighting the text. Notice that we briefly sometimes see the selection before losing it.

https://github.com/facebook/react-native/assets/153161762/b18c4235-5a7f-49af-9321-835d553d15ab

A bit more investigation reveals that the method reactFocus is later called, always after textInputDidBeginEditing. Whenever reactFocus gets called, we lose the selection. If we move the selectAll call to after reactFocus, then we consistently see the expected behavior.

https://github.com/bluesky-social/social-app/assets/153161762/b6a2c7fb-958f-4376-b634-35a935f0764e

Hopefully if this isn't the appropriate fix it at least gives someone the right idea of where to go looking.

haileyok avatar Apr 29 '24 00:04 haileyok