Skip to content

fix: don't update text input text directly in setTextAndSelection#46973

Open
hannojg wants to merge 2 commits intofacebook:mainfrom
hannojg:fix/text-input-flicker-1
Open

fix: don't update text input text directly in setTextAndSelection#46973
hannojg wants to merge 2 commits intofacebook:mainfrom
hannojg:fix/text-input-flicker-1

Conversation

@hannojg
Copy link
Contributor

@hannojg hannojg commented Oct 11, 2024

Summary:

This is one possible solution to fix the flickering issue described here:

The main fix is that when we receive the view command call setTextAndSelection we don't want to update the attributedString on the backing TextField immediately, but update the state of the shadow node.
This way the layout for the view will be calculated with the updated state, and the updated text + updated layout will be applied at once.

Changelog:

[IOS] [FIXED] - Flicker when changing text in a dynamic sized TextInput

Test Plan:

Run the tester app and make sure that every TextInput example still works as before

I added another PR which adds an explicit example case to the RNTester app:

Before changes After
Screen.Recording.2024-10-11.at.14.41.45.mov
Screen.Recording.2024-10-11.at.15.01.37.mov

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 11, 2024
@hannojg hannojg marked this pull request as ready for review October 11, 2024 12:46
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 11, 2024
@NickGerleman
Copy link
Contributor

Description here seems different from code (where the main change is we are flushing event sync).

cc @sammy-SC for sync text events. Not sure what our end goal is for them (we want to move more to sync, to avoid the sorts of issues here), but it’s not free.

@hannojg
Copy link
Contributor Author

hannojg commented Oct 11, 2024

Yes, so its two changes:

  1. Flushing events sync (so the layout gets updated immediately). This is necessary for when the user is typing, ie. the text changes are coming from the native host component (textInputDidChange)
  2. There is a second use-case, which is where the events are coming from JS (controlled input). There the problem is that we updated the host component without going through the shadow tree, ie. we are setting text without updating the layout, which we should never do i assume (see previous explanation here).

hannojg added a commit to margelo/Expensify that referenced this pull request Oct 11, 2024
const auto &textInputEventEmitter = static_cast<const TextInputEventEmitter &>(*_eventEmitter);
// When the textInputDidChange gets called, the text is already updated
// in the UI. We execute the state update synchronously so that the layout gets calculated immediately.
textInputEventEmitter.experimental_flushSync([state = _state, data = std::move(data)]() mutable {
Copy link
Contributor

Choose a reason for hiding this comment

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

the API is not ready for a general adoption. We are still iterating on the design and trying to prove its usefulness in production.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, then lets hide it behind a feature flag?

Copy link
Contributor

Choose a reason for hiding this comment

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

let me share little more context :)

First of all, the the general approach you are taking here is good. This is one of issues that sync events can fix as React Native will no longer need to do the round trip from the main thread to JS thread and back to main thread, resulting in unpleasant flicker.

As the method name suggests, the sync events are still experimental. We are not sure what the right API is at the moment. We are focusing on making the new architecture the default before fully embracing the new capabilities that is potentially breaking. experimental_flushSync works great in isolated cases but might lead to dropped frames when the JS thread is busy. We currently don't have good tools to help engineers find what the main thread is blocked on.

Once we have a good design for sync events, it will fix some issues with TextInput and significantly simplify the implementation.

facebook-github-bot pushed a commit that referenced this pull request Oct 29, 2024
Summary:
This PR adds an example showcasing a TextInput whose width gets resized dynamically based on the text content width.
This example was added for this PR, which tries to address a flickering bug with dynamic sized TextInputs:

- #46973

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

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

[INTERNAL] [ADDED] Added dynamic content width TextInput example

Pull Request resolved: #46976

Test Plan:
Test in RNTester app:

https://github.com/user-attachments/assets/7571b80b-7035-47df-b840-4218ab0802b5

Reviewed By: NickGerleman

Differential Revision: D64271454

Pulled By: arushikesarwani94

fbshipit-source-id: 28fe7bd93891ffe5284340d73e9ee947654f1788
Nodonisko pushed a commit to margelo/Expensify that referenced this pull request Mar 25, 2025
@react-native-bot
Copy link
Collaborator

This PR is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.

@react-native-bot react-native-bot added Stale There has been a lack of activity on this issue and it may be closed soon. and removed Stale There has been a lack of activity on this issue and it may be closed soon. labels Aug 25, 2025
@react-native-bot
Copy link
Collaborator

This PR is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.

@react-native-bot react-native-bot added Stale There has been a lack of activity on this issue and it may be closed soon. and removed Stale There has been a lack of activity on this issue and it may be closed soon. labels Feb 24, 2026
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. 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.

5 participants