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

Composition Events(Chinese, Japanese IME) problem in controlled components(input, textarea) #8683

Closed
eyesofkids opened this Issue Jan 4, 2017 · 5 comments

Comments

Projects
None yet
5 participants
@eyesofkids

eyesofkids commented Jan 4, 2017

Do you want to request a feature or report a bug?

both.

What is the current behavior?

There is a existed issue #3926 but it is just one of the problems in some kind of browsers.

I have uploaded the detail, demo files, test results and temporary solution in react-compositionevent

The main problem is when users type these words from IME(Chinese, Japanese or maybe Korean) and do something like search the database or filter out from some data, sometimes these functions will be unworkable. For example, if users type "ni" during the composition session, maybe it will be one of "你尼泥腻" in Chinese or one of "にニ尼煮" in Japanese. But in this moment, the change event also be fired. If the search or filter functions of the application are designed to be invoked when change event occured, there maybe something wrong logically. These functions should be invoked after users finished the composition session.

In React, there are three synthetic events - onCompositionEnd, onCompositionStart and onCompositionUpdate. If the input components(<input...> and <textarea.../>) are "uncontrolled", we can use them to help onChange to capture the text correctly. The only different point is Google Chrome change its events sequence after v53. Check Cinput.js and Ctextarea.js files.

But if these input components are "controlled", it will be hard to solve the problem.

Because these the value of a controlled component is came from state. We can't modify state directly and the only way to update state is using this.setState() to schedule update. But this.setState() may be asynchronous.

After test, i found different OS/browsers could have different results. I have written some code to solve it. But i thought it isn't a good solution. It uses the browser detection and two properties of the state object. One is for input, another is for internal functions(search, filter...etc). It can't just use one property of the state object because i can't stop any change events, state need it to update the value of the input element. If i stop some change events during composition session, i would get nothing after typing these words from IME.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/reactjs/69z2wepo/).

You can use online test demo: https://eyesofkids.github.io/
or use a normal input component(controlled/uncontrolled) to test.

What is the expected behavior?

The input(and textarea) controlled components in React should ensure these fired "change" and "composition" events is consistent in different browsers. I found there are 3 different results(events fired sequence) at least.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

  • React 15.4.1
  • browsers: chrome, firefox, safari, opera, ie, edge
  • OS: macOS, win7, win10
@eyesofkids

This comment has been minimized.

Show comment
Hide comment
@eyesofkids

eyesofkids Jan 7, 2017

related to pull request #8438

eyesofkids commented Jan 7, 2017

related to pull request #8438

@zuimeiaj

This comment has been minimized.

Show comment
Hide comment
@zuimeiaj

zuimeiaj Sep 6, 2017

onCompositionUpdate={(e)=>this.chInProcessing=true}
onChange={()=>{
   if(this.chInProcessing){
            this.chInProcessing=false;
            return ;
        }

}}

demo

zuimeiaj commented Sep 6, 2017

onCompositionUpdate={(e)=>this.chInProcessing=true}
onChange={()=>{
   if(this.chInProcessing){
            this.chInProcessing=false;
            return ;
        }

}}

demo

@DJTB

This comment has been minimized.

Show comment
Hide comment
@DJTB

DJTB Jan 23, 2018

@zuimeiaj this approach instantly closes the IME composition box and completely blocks all input using Google (Japanese) IME (on Ubuntu 16.04 / Chrome 63).

@eyesofkids is completely right in saying "I found there are 3 different results (events fired sequence) at least." (in different browsers). There's definitely inconsistency between browser implementations as to when and how many times they fire start/change/end.

This may not have any implications as regards React onChange but it's also worth mentioning that some software keyboards on mobile devices also fire composition events for autocomplete suggestions. Note that this is even with normal English input (latin characters), so the general problem isn't necessarily restricted to just Chinese Japanese etc IME composition.

DJTB commented Jan 23, 2018

@zuimeiaj this approach instantly closes the IME composition box and completely blocks all input using Google (Japanese) IME (on Ubuntu 16.04 / Chrome 63).

@eyesofkids is completely right in saying "I found there are 3 different results (events fired sequence) at least." (in different browsers). There's definitely inconsistency between browser implementations as to when and how many times they fire start/change/end.

This may not have any implications as regards React onChange but it's also worth mentioning that some software keyboards on mobile devices also fire composition events for autocomplete suggestions. Note that this is even with normal English input (latin characters), so the general problem isn't necessarily restricted to just Chinese Japanese etc IME composition.

@LeoEatle

This comment has been minimized.

Show comment
Hide comment
@LeoEatle

LeoEatle Apr 17, 2018

I also found that not only browser behaves differently in the sequence of emitting composition events and onInput events. The different IME may also behave differently in these events. For example, the native Apple keyboard in iOS will emit composition event after the input event. But if you use Google keyboard, the composition event will never be emitted.
It's very important to implement the same standard for this basic thing.

LeoEatle commented Apr 17, 2018

I also found that not only browser behaves differently in the sequence of emitting composition events and onInput events. The different IME may also behave differently in these events. For example, the native Apple keyboard in iOS will emit composition event after the input event. But if you use Google keyboard, the composition event will never be emitted.
It's very important to implement the same standard for this basic thing.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 29, 2018

Member

I'm going to close this as a duplicate of #3926 — but I appreciate the extra details in this issue. I'll include them into the original issue.

Member

gaearon commented Aug 29, 2018

I'm going to close this as a duplicate of #3926 — but I appreciate the extra details in this issue. I'll include them into the original issue.

@gaearon gaearon closed this Aug 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment