Skip to content
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

TextInput onChangeText is called with empty text if maxLength is exceeded on iOS #28774

Closed
andreaspalsson opened this issue Apr 28, 2020 · 15 comments
Labels
Component: TextInput Related to the TextInput component. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍 Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@andreaspalsson
Copy link

Description

If the max length of a controlled TextInput is exceeded on iOS onChangeText will get called with an empty string. We noticed this issue when our users added an emoji as the last character in a TextInput. We only see the issue on iOS, on Android the the emoji can not be added. Since emojis are counted as two chars I'm guessing the emoji is causing the text to have length maxLength+1 and that is causing issues on iOS.

Using an uncontrolled TextInput the emoji is replace with the last character in the screenshot below but keeps it's value.
Screenshot 2020-04-28 at 14 48 00

React Native version:

0.61.4

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. Create a controlled TextInput with a maxLength
  2. Input text until you reach maxLength - 1
  3. Add a emoji

Expected Results

Same behaviour as on Android that the emoji is not accepted as input.

Snack, code example, screenshot, or link to a repository:

https://snack.expo.io/8x3dBwzJe

@react-native-bot react-native-bot added Component: TextInput Related to the TextInput component. Platform: iOS iOS applications. labels Apr 28, 2020
@chrisglein chrisglein added the Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. label Apr 29, 2020
@stale
Copy link

stale bot commented Jul 29, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jul 29, 2020
@andreaspalsson
Copy link
Author

Reran the snack it with latest version of Expo v38.0.0 and React Native 0.62.2 and the issue is still there.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 6, 2020
@stale
Copy link

stale bot commented Dec 26, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 26, 2020
@ghost
Copy link

ghost commented Mar 19, 2021

Same issue here...

Screen.Recording.2021-03-19.at.10.09.59.mov

As you can see on video, when I exceed the maximum length of the input it is automatically cleared.
An emoji is equivalent to 2 characters, when my input has 119 (maxLength 120) and I type an emoji it goes to 121 of length and the input is cleared. But if I reach exactly 120 characters it will not happen.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Mar 19, 2021
@ghost
Copy link

ghost commented Mar 19, 2021

As a workaround I've removed maxLength prop and added the following code to the onChangeText callback:

onChangeText={value => {
    if (value.length <= maxLength) {
        setNewValue(value)
    }
}}

It minimizes the chances of the bug happening but doesn't fix it.

@RishavKumar-3796
Copy link

Please resolve this !

@AlbertVilaCalvo
Copy link

As a workaround I've removed maxLength prop and added the following code to the onChangeText callback:

onChangeText={value => {
    if (value.length <= maxLength) {
        setNewValue(value)
    }
}}

It minimizes the chances of the bug happening but doesn't fix it.

I don't see any difference with this. Eg if the max length is 20 and I've written 19 chars, and then I add an emoji, it always clears the whole input text.

My understanding is that an emoji counts like 2 chars in terms of max length, because in my case I have a max length of 20, and I can write either 20 chars max, or 10 emoji max. Hence, when I have 19 chars and I add an emoji it's like having 21 chars, which is beyond the max length, which triggers the input clearing.

@AlbertVilaCalvo
Copy link

This comment is interesting: #24109 (comment)

we have a ton of code that on the backend expects maxLength to adhere to the real length and not the human readable length.

we may want to add another prop that explicitly specifies the max length is based on the glyph count instead of the number of bytes and make people opt-in to use that prop in the cases where the human readable length matters to them.

@AlbertVilaCalvo
Copy link

I've found a workaround that fixes the issue:

import * as React from 'react'
import { Platform, TextInput, TextInputProps } from 'react-native'

export interface TextInputFixedProps extends TextInputProps {
  onChangeText: (text: string) => void
}

/**
 * Workaround for https://github.com/facebook/react-native/issues/28774
 * and https://github.com/status-im/status-react/issues/12919.
 *
 * Fixes `onChange` clearing the whole input when an emoji is typed as the last
 * character when having `maxLength`. This happens on iOS only.
 *
 * Requires `onChangeText` to be set.
 */
export function TextInputFixed(props: TextInputFixedProps) {
  if (Platform.OS === 'ios') {
    return (
      <TextInput
        {...props}
        onChangeText={undefined}
        onChange={(event) => {
          const newText = event.nativeEvent.text
          const currentText = event._dispatchInstances.memoizedProps.text
          const clearsInput =
            props.maxLength &&
            currentText.length === props.maxLength - 1 &&
            newText.length === 0
          if (!clearsInput) {
            props.onChangeText(newText)
          }
        }}
      />
    )
  } else {
    return <TextInput {...props} />
  }
}

It's a bit ugly to access the private _dispatchInstances, but it does work.

I'm using React Native ~0.63.4.

@athakur3
Copy link

athakur3 commented Aug 5, 2022

textInput_emoji_issue.mov

Hi, I'm not able to reproduce on snack. Am I missing something??

@athakur3
Copy link

athakur3 commented Aug 5, 2022

@AlbertVilaCalvo We can close this, if this is fixed in 0.69?

@AlbertVilaCalvo
Copy link

@athakur3 I have not upgraded to 0.69 so I don't know if it's fixed.
Also, to be sure it's fixed you should try it on a real iPhone or iOS emulator, not snack.

@github-actions
Copy link

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.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Apr 24, 2023
@github-actions
Copy link

github-actions bot commented May 1, 2023

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

@github-actions github-actions bot closed this as completed May 1, 2023
@shridharkalagi
Copy link

This issue is still existing. Is it being fixed?

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. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍 Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests

7 participants