Skip to content

fix: onChangeText should be called only once if changed via js in a multiline textinput#45401

Closed
deepanshushuklad11 wants to merge 1 commit intofacebook:mainfrom
deepanshushuklad11:fix/onchange_called_multipletimes
Closed

fix: onChangeText should be called only once if changed via js in a multiline textinput#45401
deepanshushuklad11 wants to merge 1 commit intofacebook:mainfrom
deepanshushuklad11:fix/onchange_called_multipletimes

Conversation

@deepanshushuklad11
Copy link
Contributor

@deepanshushuklad11 deepanshushuklad11 commented Jul 12, 2024

Fixes 44566

Summary:

Issue was onChangeText was called 5-6 times if maxLength was set in a multiline component and TextInput Value was changed via state update.
`if (_maxLength) {
NSInteger allowedLength = MAX(
_maxLength.integerValue - (NSInteger)backedTextInputView.attributedText.string.length + (NSInteger)range.length,
0);

if (text.length > allowedLength) {
  // If we typed/pasted more than one character, limit the text inputted.
  if (text.length > 1) {
    if (allowedLength > 0) {
      // make sure unicode characters that are longer than 16 bits (such as emojis) are not cut off
      NSRange cutOffCharacterRange = [text rangeOfComposedCharacterSequenceAtIndex:allowedLength - 1];
      if (cutOffCharacterRange.location + cutOffCharacterRange.length > allowedLength) {
        // the character at the length limit takes more than 16bits, truncation should end at the character before
        allowedLength = cutOffCharacterRange.location;
      }
    }
    // Truncate the input string so the result is exactly maxLength
    NSString *limitedString = [text substringToIndex:allowedLength];
    NSMutableAttributedString *newAttributedText = [backedTextInputView.attributedText mutableCopy];
    // Apply text attributes if original input view doesn't have text.
    if (backedTextInputView.attributedText.length == 0) {
      newAttributedText = [[NSMutableAttributedString alloc]
          initWithString:[self.textAttributes applyTextAttributesToText:limitedString]
              attributes:self.textAttributes.effectiveTextAttributes];
    } else {
      [newAttributedText replaceCharactersInRange:range withString:limitedString];
    }
    backedTextInputView.attributedText = newAttributedText;
    _predictedText = newAttributedText.string;

    // Collapse selection at end of insert to match normal paste behavior.
    UITextPosition *insertEnd = [backedTextInputView positionFromPosition:backedTextInputView.beginningOfDocument
                                                                   offset:(range.location + allowedLength)];
    [backedTextInputView setSelectedTextRange:[backedTextInputView textRangeFromPosition:insertEnd
                                                                              toPosition:insertEnd]
                               notifyDelegate:YES];

    [self textInputDidChange];
  }

  return nil; // Rejecting the change.
}}`

This is the original code snippet.
It was happening because of wrong check of maxLength with text length if (text.length > allowedLength) this should be
(text.length > _maxLength.integerValue) and if (allowedLength <= 0) we should not change the string and fire textInputDidChange

Changelog:

[IOS] [FIXED] : Fixing maxLength check which was firing onChange multiple times

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

Test Plan:

Tested in Ios
Ran yarn test
Screenshot 2024-07-12 at 1 00 28 PM

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Jul 12, 2024
@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 21,268,015 +136
android hermes armeabi-v7a n/a --
android hermes x86 n/a --
android hermes x86_64 n/a --
android jsc arm64-v8a 24,465,006 +15
android jsc armeabi-v7a n/a --
android jsc x86 n/a --
android jsc x86_64 n/a --

Base commit: d68a177
Branch: main

@deepanshushuklad11
Copy link
Contributor Author

@cortinico @cipolleschi Any update on this

Copy link
Contributor

@cipolleschi cipolleschi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @deepanshushuklad11, thanks for the fix and sorry for te late reply. I missed the PR on friday.

I see that this is the fix only for the Old Arch. Can you verify whether the problem exists also in the New Arch and fix it there as well?
The component where I'd start looking into is RCTTextInputComponentView.

Thank you so much!

@deepanshushuklad11
Copy link
Contributor Author

Hi @deepanshushuklad11, thanks for the fix and sorry for te late reply. I missed the PR on friday.

I see that this is the fix only for the Old Arch. Can you verify whether the problem exists also in the New Arch and fix it there as well? The component where I'd start looking into is RCTTextInputComponentView.

Thank you so much!

@cipolleschi Its not happening on new arch

@deepanshushuklad11
Copy link
Contributor Author

@cipolleschi Anything else required from my end?

@facebook-github-bot
Copy link
Contributor

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@cipolleschi
Copy link
Contributor

Sorry for the delay! I imported the PR, let's see if the internal CI is happy about it!

@deepanshushuklad11
Copy link
Contributor Author

Sorry for the delay! I imported the PR, let's see if the internal CI is happy about it!

Hey @cipolleschi any update ?

@cipolleschi
Copy link
Contributor

Hi @deepanshushuklad11, sorry for the delay, I have been quite busy the past week. I'll try to get to it this week.

@facebook-github-bot
Copy link
Contributor

@cipolleschi merged this pull request in d88dd14.

@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Jul 31, 2024
@react-native-bot
Copy link
Collaborator

This pull request was successfully merged by @deepanshushuklad11 in d88dd14

When will my fix make it into a release? | How to file a pick request?

facebook-github-bot pushed a commit that referenced this pull request Dec 10, 2024
Summary:
Fixes #47563

It seems like a regression from #45401, where it was aimed to fix `onChangeText` being called multiple times when changing the text programmatically in an input with the `multiline` prop set as true.

This PR reverts that partially, as the `maxLength` check is not being evaluated correctly before setting the text. Not reverting it completely as when removing the second part of the fix, the `onChangeText` gets called multiple times again.

## Changelog:

[IOS] [FIXED] - Fixing TextInput `maxLength` not working in old arch

Pull Request resolved: #48126

Test Plan:
The issue could be reproduced in the rn-tester. See my videos with the before and after the fix.

<details>
<summary>Before:</summary>

https://github.com/user-attachments/assets/86fd67eb-fc14-469a-a5f8-8e83b49f857c

</details>

<details>
<summary>After:</summary>

https://github.com/user-attachments/assets/368383b1-c1bd-4e0b-ac44-c78022462fa0

</details>

Reviewed By: cortinico

Differential Revision: D67025182

Pulled By: cipolleschi

fbshipit-source-id: 720c400eef362618106ae434aef421c7529214fe
cipolleschi pushed a commit that referenced this pull request Jan 8, 2025
Summary:
Fixes #47563

It seems like a regression from #45401, where it was aimed to fix `onChangeText` being called multiple times when changing the text programmatically in an input with the `multiline` prop set as true.

This PR reverts that partially, as the `maxLength` check is not being evaluated correctly before setting the text. Not reverting it completely as when removing the second part of the fix, the `onChangeText` gets called multiple times again.

## Changelog:

[IOS] [FIXED] - Fixing TextInput `maxLength` not working in old arch

Pull Request resolved: #48126

Test Plan:
The issue could be reproduced in the rn-tester. See my videos with the before and after the fix.

<details>
<summary>Before:</summary>

https://github.com/user-attachments/assets/86fd67eb-fc14-469a-a5f8-8e83b49f857c

</details>

<details>
<summary>After:</summary>

https://github.com/user-attachments/assets/368383b1-c1bd-4e0b-ac44-c78022462fa0

</details>

Reviewed By: cortinico

Differential Revision: D67025182

Pulled By: cipolleschi

fbshipit-source-id: 720c400eef362618106ae434aef421c7529214fe
robhogan pushed a commit that referenced this pull request Jan 15, 2025
Summary:
Fixes #47563

It seems like a regression from #45401, where it was aimed to fix `onChangeText` being called multiple times when changing the text programmatically in an input with the `multiline` prop set as true.

This PR reverts that partially, as the `maxLength` check is not being evaluated correctly before setting the text. Not reverting it completely as when removing the second part of the fix, the `onChangeText` gets called multiple times again.

## Changelog:

[IOS] [FIXED] - Fixing TextInput `maxLength` not working in old arch

Pull Request resolved: #48126

Test Plan:
The issue could be reproduced in the rn-tester. See my videos with the before and after the fix.

<details>
<summary>Before:</summary>

https://github.com/user-attachments/assets/86fd67eb-fc14-469a-a5f8-8e83b49f857c

</details>

<details>
<summary>After:</summary>

https://github.com/user-attachments/assets/368383b1-c1bd-4e0b-ac44-c78022462fa0

</details>

Reviewed By: cortinico

Differential Revision: D67025182

Pulled By: cipolleschi

fbshipit-source-id: 720c400eef362618106ae434aef421c7529214fe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TextInput (IOS) : maxLength & multiline true = onChangeText multiple call

5 participants