[core] fix(AsyncControllableInput): handle compound composition events #5165
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There's an issue with the AsyncControllableInput, where Korean input can lead to incorrect values being stored.
The Bug
The cause is the way that Korean handles keyboard events: letters in the Korean language are combined into symbols, which are bubbled up as CompositionEvents. For instance, when typing the characters
ㄷ
->ㅣ
->ㄱ
->ㅏ
, they would successively render asㄷ
,디
,딕
,디가
- note that with the last input the value splits out into two characters, which manifests as one CompositionEvent (디
) ending and then a new one (가
) immediately starting. I put together some logging to show the flow (times in seconds, logging code here):Currently, this gives incorrect results with AsyncControllableInput: because the
value
prop can be updated on a delay (eg. example from the docs), when the first composition ends the stored value (디
) is blown away by the old state (딕
), which results in the incorrect final result닥가
(note the extraㄱ
in the first character).The solution
As far as I can tell, there's no way in the onCompositionEnd callback to determine whether another CompositionEvent is about to start. If that's the case, the best solution I can think of is to manually wait to unlock the component for edits after some time delay - I've chosen 10ms, because in my experimentation it was always <=1ms before the next event started.
Checklist
Is there documentation I should add?