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

`maxLength` of TextInput does not work when value is changed after state update

Open kunalchavhan opened this issue 1 year ago • 5 comments
trafficstars

Description

maxLength of Text Input is not working when value is changed after state update. It works as expected when input is given with keyboard. <TextInput style={styles.textInput} value={description} maxLength={10} onChangeText={text => setDescription(text)} />

Steps to reproduce

  1. Set maxLength of TextInput to any non zero number
  2. Store any text in state
  3. Use text stored in state as value in TextInput
  4. Update the state with text length greater than maxLength
  5. TextInput will have text which has length greater than given maxLength

React Native Version

0.74.2

Affected Platforms

Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 13.5.1
  CPU: (10) arm64 Apple M1 Max
  Memory: 73.36 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.12.0
    path: ~/.nvm/versions/node/v18.12.0/bin/node
  Yarn:
    version: 3.6.4
    path: /opt/homebrew/bin/yarn
  npm:
    version: 8.19.2
    path: ~/.nvm/versions/node/v18.12.0/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.14.3
    path: /Users/kunal.chavhan/.rvm/gems/ruby-3.2.2/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.0
      - iOS 17.0
      - macOS 14.0
      - tvOS 17.0
      - watchOS 10.0
  Android SDK: Not Found
IDEs:
  Android Studio: Jellyfish 2023.3.1 Patch 2 Jellyfish 2023.3.1 Patch 2
  Xcode:
    version: 15.0/15A240d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /usr/bin/javac
  Ruby:
    version: 3.2.2
    path: /Users/kunal.chavhan/.rvm/rubies/ruby-3.2.2/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.2
    wanted: 0.74.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

NA

Reproducer

https://github.com/kunalchavhan/rn-textinput-maxlength-reproducer

Screenshots and Videos

https://github.com/facebook/react-native/assets/61144478/4a377ec3-e60a-46ad-b54d-c6362ebd8622

kunalchavhan avatar Jun 15 '24 06:06 kunalchavhan

I was debugging this and found that this method is getting called whenever text is updated from react's state change. This method then calls setAttributedString which then sets the text. I could not find any checks here for maxLength prop.

When input is received from keyboard this method is called which has maxLength prop check.

Any reason for not checking maxLength prop here also?

kunalchavhan avatar Jun 15 '24 12:06 kunalchavhan

@sammy-SC could you please take a look into this? Thank you for your time.

kunalchavhan avatar Jun 20 '24 08:06 kunalchavhan

I was debugging this and found that this method is getting called whenever text is updated from react's state change. This method then calls setAttributedString which then sets the text. I could not find any checks here for maxLength prop.

When input is received from keyboard this method is called which has maxLength prop check.

Any reason for not checking maxLength prop here also?

The code you are linking is for the new architecture but your repro is with the old architecture. For the old architecture, maxLength is handled here. It appears maxLength is not taken account for when the update comes from React.

This can be annoying but there is a simple workaround if this is blocking you. When setting text from React, you can check for the length of new text value and shorten it if it goes over the maxLength. maxLength is important for the updates to TextInput coming from native, because there your JavaScript code doesn't have a a chance to run. Thanks to maxLength prop, you have a chance to prevent iOS from painting TextInput with value that is longer than maxLength.

sammy-SC avatar Jun 24 '24 08:06 sammy-SC

The code you are linking is for the new architecture but your repro is with the old architecture. For the old architecture, maxLength is handled here. It appears maxLength is not taken account for when the update comes from React.

This can be annoying but there is a simple workaround if this is blocking you. When setting text from React, you can check for the length of new text value and shorten it if it goes over the maxLength. maxLength is important for the updates to TextInput coming from native, because there your JavaScript code doesn't have a a chance to run. Thanks to maxLength prop, you have a chance to prevent iOS from painting TextInput with value that is longer than maxLength.

Thank you for the clarification and sorry for wrong linking of code. I pushed repro for new architecture here.

Thank you for suggesting workaround. I have checked that the maxLength prop works for updates from React on android. Would it be possible to have the same behaviour on iOS also?

kunalchavhan avatar Jun 24 '24 09:06 kunalchavhan

Thank you for the clarification and sorry for wrong linking of code. I pushed repro for new architecture here.

Thank you for suggesting workaround. I have checked that the maxLength prop works for updates from React on android. Would it be possible to have the same behaviour on iOS also?

@sammy-SC if you agree that iOS should handle maxLength on updates from react, can I try to resolve this?

kunalchavhan avatar Jun 27 '24 09:06 kunalchavhan

Issue still appears on iOS with react-native version 0.76.1. Any updates?

vanBerloDevelopments avatar Nov 14 '24 15:11 vanBerloDevelopments

+1 still an issue on 76.5. The maxLength property is not working for me.

ChristopherGabba avatar Dec 22 '24 12:12 ChristopherGabba

+1 maxLength property is not working on v0.76.5.

johaan22 avatar Jan 04 '25 04:01 johaan22

@vanBerloDevelopments @ChristopherGabba @johaan22 Are you all sure you're hitting the specific issue of maxLength not working after state update? Or are you hitting the general issue of maxLength not working at all on iOS? If it's the latter a fix has already been merged and will be released in 0.78. See https://github.com/facebook/react-native/issues/47563

Tobbe avatar Jan 07 '25 04:01 Tobbe

@Tobbe, I'm honestly not sure which it is. I'm definitely using TextInputs like I have always used them:


const [textValue, setTextValue] = useState("")

 <TextInput 
        maxLength={10}
        value={textValue}
        onChangeText={setTextValue}
 />

And it lets me just type straight past 10 with not even a bobble. I have not tested this on Android, but it is for sure happening on iOS.

ChristopherGabba avatar Jan 07 '25 13:01 ChristopherGabba

@ChristopherGabba, yeah, that's #47563. We'll have to wait for 0.78 to get access to the fix

Tobbe avatar Jan 07 '25 15:01 Tobbe

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

react-native-bot avatar Jul 07 '25 05:07 react-native-bot

This issue was closed because it has been stalled for 7 days with no activity.

react-native-bot avatar Jul 14 '25 05:07 react-native-bot