React: Das Änderungsereignis wird zusätzliche Zeiten ausgelöst, bevor die IME-Komposition endet

Erstellt am 21. Mai 2015  ·  48Kommentare  ·  Quelle: facebook/react

Zusätzliche Details


Ursprüngliches Problem

Als ich dieses Beispiel aus https://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html ausprobierte,

screen shot 2015-05-21 at 14 04 36

Eigentlich würde ich erwarten, dass diese nicht feuern, bevor ich das chinesische Schriftzeichen bestätige.

Dann habe ich eine andere Art von Eingabemethode ausprobiert - die Wubi-Eingabemethode. Ich habe Folgendes erhalten:

screen shot 2015-05-21 at 14 17 15

Es ist auch komisch. Also habe ich einen Test in jQuery gemacht :

screen shot 2015-05-21 at 14 05 12

Erst nachdem ich die Leertaste gedrückt habe, um den Charakter zu bestätigen, wird das Ereignis keyup ausgelöst.

Ich weiß, dass es zwischen der Implementierung von jQuery keyup und der Reaktion von onChange , aber ich würde erwarten, wie jQuery keyup mit chinesischen Zeichen umgeht, anstatt mit onChange reagieren

DOM Bug

Hilfreichster Kommentar

Hallo Facebook-Leute, tatsächlich verursacht dieses Problem ein ernstes Problem: Wir können die Eingabe nicht asynchron mit der chinesischen Eingabe aktualisieren.
Zum Beispiel können wir keine meteorreaktiven Datenquellen oder Speicher wie Redux verwenden, da alle Rückmeldungen asynchron aktualisiert werden.
Hier ist ein einfachstes Beispiel, um dieses Problem zu zeigen: Verwenden Sie setTimeout, um ein asynchrones Update durchzuführen:
https://jsfiddle.net/liyatang/bq6oss6z/1/

Ich hoffe wirklich, dass Sie dies schnell beheben können, damit wir nicht die Mühe verschwenden, es hier und da und immer wieder zu umgehen.

Vielen Dank.

Hier ist meine Problemumgehung . Wenn jemand das gleiche Problem hat, können Sie einen Blick darauf werfen

Alle 48 Kommentare

cc @salier :) - Was sollen wir hier tun?

Ich denke, wir sollten onChange erst feuern, wenn der IME-String festgeschrieben ist.

Eine Möglichkeit, dies in ChangeEventPlugin zu handhaben, besteht darin, alle input -Ereignisse zwischen compositionstart und compositionend zu ignorieren und dann das Ereignis input sofort zu verwenden folgenden compositionend .

Ich habe einige schnelle Tests unter OSX Chrome und Firefox mit Simplified Pinyin und 2-Set Korean durchgeführt, und die Ereignisreihenfolge und die Daten scheinen korrekt genug zu sein. (Ich gehe davon aus, dass wir Probleme mit IE Koreanisch haben werden, aber wir können Glück haben.)

Ich denke, wir sehen möglicherweise weiterhin Probleme mit alternativen Eingabemethoden wie der Google Input Tools-Erweiterung, aber es gibt möglicherweise Problemumgehungen dafür.

Dies beeinflusst auch, wie dialektische Zeichen für lateinische Sprachen eingegeben werden. Sogar das lange Drücken von e und die anschließende Verwendung der Variante scheitern hier.

Entschuldigung, das scheint nicht verwandt zu sein. Entschuldigen Sie.

Gibt es Neuigkeiten dazu? Ich leide auch unter diesem Problem.

Derzeit keine - dies hat für uns derzeit keine hohe Priorität. Ich würde mich freuen, eine Pull-Anfrage zu prüfen, wenn jemand versucht, dies zu beheben.

@salier Es scheint, als würde der IE nach compositionend kein input -Ereignis auslösen . Ich habe auf IE11 und Edge unter Windows 10 getestet. Es wird ordnungsgemäß in Chrome und Firefox ausgelöst.

In 9 wird das Änderungsereignis zu oft ausgelöst, wenn chinesische Zeichen erneut eingegeben werden

Hallo Facebook-Leute, tatsächlich verursacht dieses Problem ein ernstes Problem: Wir können die Eingabe nicht asynchron mit der chinesischen Eingabe aktualisieren.
Zum Beispiel können wir keine meteorreaktiven Datenquellen oder Speicher wie Redux verwenden, da alle Rückmeldungen asynchron aktualisiert werden.
Hier ist ein einfachstes Beispiel, um dieses Problem zu zeigen: Verwenden Sie setTimeout, um ein asynchrones Update durchzuführen:
https://jsfiddle.net/liyatang/bq6oss6z/1/

Ich hoffe wirklich, dass Sie dies schnell beheben können, damit wir nicht die Mühe verschwenden, es hier und da und immer wieder zu umgehen.

Vielen Dank.

Hier ist meine Problemumgehung . Wenn jemand das gleiche Problem hat, können Sie einen Blick darauf werfen

Ich habe ein einfaches Beispiel erstellt, um zu demonstrieren, wie compositionstart und compositionend Ereignisse verwendet werden, um die Eingabe von chinesischem IME für onchange Ereignisprobleme zu verhindern.
Hier ist der Link: https://jsfiddle.net/eyesofkids/dcxvas28/8/

@eyesofkids gute Arbeit, dies könnte als Standardimplementierung von onChange für Eingabe, Textbereich ...

gute Arbeit !

Ich hatte das gleiche Problem und die Problemumgehung von @eyesofkids funktioniert perfekt (danke!).

Nachdem ich die Problemumgehung eingerichtet hatte, tauchte ich in den Quellcode von React ein, um zumindest zu versuchen, einen fehlgeschlagenen Test hinzuzufügen - in der Hoffnung, später das erwartete Verhalten zur Bibliothek hinzuzufügen -, obwohl es für jemanden, der mit den Interna nicht vertraut ist, etwas kompliziert erscheint.

Anfangs hatte ich erwartet, dass ein Test ähnlich dem, der bereits für ChangeEventPlugin verfügbar ist, funktionieren sollte, dh ein natives compositionStart / compositionUpdate simulieren und prüfen, ob kein onChange Rückruf vorhanden ist gefeuert; Das Überprüfen von onChange erst ausgelöst, wenn compositionEnd simuliert wurde. Dies scheint jedoch nicht zu funktionieren.

Daher dachte ich, dass es vielleicht machbar wäre, nach ChangeEventPlugin.extractEvents() zu suchen, ähnlich wie bei den Tests für SelectEventPlugin . Hier bekomme ich aus irgendeinem Grund immer undefined wenn ich die Ereignisse extrahiere.
Als Referenz ist dies der Testcode, den ich in _ChangeEventPlugin-test.js_ ausprobiert habe:

  var EventConstants = require('EventConstants');
  var ReactDOMComponentTree = require('ReactDOMComponentTree');
  var topLevelTypes = EventConstants.topLevelTypes;

  function extract(node, topLevelEvent) {
    return ChangeEventPlugin.extractEvents(
      topLevelEvent,
      ReactDOMComponentTree.getInstanceFromNode(node),
      {target: node},
      node
    );
  }

  function cb(e) {
    expect(e.type).toBe('change');
  }
  var input = ReactTestUtils.renderIntoDocument(
    <input onChange={cb} value='foo' />
  );

  ReactTestUtils.SimulateNative.compositionStart(input);

  var change = extract(input, topLevelTypes.topChange);
  expect(change).toBe(null);

Ich fürchte, ich weiß nicht genau, wie man diese Tests debuggen soll - sonst hätte ich ein klareres Bild davon, was los ist. Jede Anleitung zum weiteren Vorgehen oder andere Hinweise wären sehr dankbar.

Die Problemumgehung ist in Chrome 53+ plötzlich aufgetreten und scheint nicht mehr gültig zu sein, da die Reihenfolge geändert wurde, in der compositionend ausgelöst wurde : Früher geschah dies vor textInput , jetzt nach textInput . Infolgedessen wird change nicht ausgelöst, wenn es während der Komposition abgebrochen wird 😕.

https://github.com/suhaotian/react-input hilft vielleicht jemandem

Für Chrome v53 gibt es eine knifflige Lösung. So rufen Sie den Handlechange auf, nachdem compositionend ausgelöst wurde.

handleComposition  = (event) => {

    if(event.type === 'compositionend'){
      onComposition = false

      //fire change method to update for Chrome v53
      this.handleChange(event)

    } else{
      onComposition = true
    }
  }

Überprüfen Sie die Demo hier: https://jsfiddle.net/eyesofkids/dcxvas28/11/

@chenxsan hast du die Lösung gefunden?
Sie können den CompositionStart erkennen und eine Variable gleich true lassen.
Verwenden Sie dann die von Ihnen festgelegte Variable bei onChange, um zu prüfen, ob die Abfrage ausgelöst werden soll

Ich habe in # 8683 ein neues Problem für gesteuerte Komponenten

Die temporäre Lösung für die unkontrollierte und gesteuerten Komponenten (Eingang, TextArea-) hochgeladen reagieren-compositionevent .

@yesmeck sehr glücklich, diese Nachrichten zu sehen.

Ich habe gesehen, dass sich der Test nur auf das Webkit konzentriert. Es sollte in Chrome und Safari getrennt sein, da Chrome seine durch Ereignisse ausgelöste Reihenfolge compositionend nach 53+ ändert.

@eyesofkids Ein neuer Testfall für Chrome unter 53 wurde hinzugefügt.

Um dem Feuer Treibstoff hinzuzufügen, habe ich versucht, dieses Problem zu umgehen, und festgestellt, dass die aktuelle Version der iOS-Safari bei Verwendung des japanischen Hiragana IME nicht das Ereignis compositionend auslöst. Ich denke, dies ist beabsichtigt Das Kompositionsmenü scheint nie geschlossen zu sein.
Auf @eyesofkids Umgehung Beispiel die Inputvalue wird nie aktualisiert, für mich aber https://github.com/zhaoyao91/react-optimistic-input das Problem mit dem japanischen IME fixiert.

Für alle, die nach einer Lösung suchen, ist hier eine gebrauchsfertige Komponente. https://github.com/aprilandjan/react-starter/blob/test/search-input/src/components/SearchInput.js Verwenden Sie es einfach anstelle des normalen Texteingabeelements und alles ist in Ordnung.

@ zhaoyao91 Ihre Abhilfe funktioniert einfach! vielen Dank.

Hey Leute, gibt es Neuigkeiten in dieser Ausgabe?

Es hat keine hohe Priorität, da das zu häufige Brennen von onChange selten Probleme verursacht. Wo verursacht es Probleme in Ihrer App?

@sophiebits sorry hat versehentlich auf das 'X' geklickt. Dies kann die Leistung beeinträchtigen, wenn Filtervorgänge oder Serverrückrufe in den Änderungsereignishandlern verwendet werden. Der in https://github.com/facebook/react/issues/3926#issuecomment -316049951 gezeigte Ansatz ist eine gute Problemumgehung für unkontrollierte oder native Eingaben, lässt sich jedoch nicht gut auf reaktionsgesteuerte Eingaben abbilden. Es scheint, als hätten einige in diesem Thread versucht, eine PR zu entwickeln, fanden die Interna jedoch etwas komplex - aber vielleicht könnte ein Ingenieur in Ihrem Team schneller daran arbeiten? https://github.com/facebook/react/issues/8683 ist eine viel bessere Beschreibung des eigentlichen Problems IMO.

Kann mir bitte jemand helfen zu verstehen: Liegt das Problem ausschließlich in zusätzlichen onChange Anrufen in der Mitte ? Oder bekommen Sie am Ende einen falschen Wert?

Der Test aus dem Fixversuch in https://github.com/facebook/react/pull/8438 besteht, wenn ich die Behauptung über die Häufigkeit des Aufrufs von onChange entferne. Ich nehme an, dieses Problem betrifft nur die zusätzlichen onChange -Anrufe.

Es gibt keine zusätzlichen onChange-Aufrufe, es wird nur der falsche Wert am Ende angezeigt, es scheint eher ein onComposition-Problem zu sein.

@crochefluid Können Sie einen fehlgeschlagenen Test dafür erstellen? Ähnlich wie bei # 8438. In diesem Test gab es keinen falschen Wert.

@gaearon Ich werde es versuchen. Haben Sie diesen Test auf Safari (Mac / IOS) versucht?

Es ist ein Knotentest, der jedoch Sequenzen codiert, die von verschiedenen Browsern und Geräten erfasst wurden. Bitte beachten Sie die Quelle. Sie müssten fehlgeschlagene Sequenzen hinzufügen.

Ich nehme an, dass es bei diesem Problem nur um die zusätzlichen onChange-Aufrufe geht.

Genau.

Ich bekomme immer noch dieses Problem. Es sieht so aus, als ob dieses Problem seit 3 ​​Jahren offen ist. Unterstützt React derzeit chinesische Eingaben in gesteuerte Komponenten?

Auch auf Japanisch mit bestimmten Zeichen zu sehen ...

Hier ist eine Code-Sandbox, die mein Problem reproduziert. Sieht aus wie es mit Formularen zusammenhängt. Die direkte Verwendung von Eingaben ist in Ordnung.

https://codesandbox.io/s/0m1760xqnl

Ich habe einige Fälle hinzugefügt:
Die Verwendung des Reaktionszustands und der einfachen Eingaben ist in Ordnung
Die Verwendung des Reaktionszustands, einfacher Formen und einfacher Eingaben ist in Ordnung
Wir verwenden eine kontextbasierte Formularkomponente, die nicht funktioniert. Möglicherweise handelt es sich um ein kontextbezogenes Problem.

Problem gelöst: Ich habe es im Codepen zum Laufen gebracht. Aus irgendeinem Grund funktionierte die Übergabe von 'Eingabe' als Komponente beim Übergeben von (Requisiten) => nicht.

Hat jemand eine Idee, was der Unterschied ist?

Eigentlich habe ich auch versucht:

Funktioniert

<Field {...otherProps} component="input" />

Funktioniert nicht

<Field {...otherProps} component={(props) => <input {...props} />} />

Funktioniert seltsamerweise

const WrappedInput = (props) => <input {...props} />
...
<Field {...otherProps} component={WrappedInput} />

Es ist klar, dass hier etwas Magisches vor sich geht, das ich nicht verstehe. 😕

Irgendwelche Updates?

Es scheint ein falsches Ergebnis zu verursachen, wenn IME aktiviert ist

e84721f3ec71a5ce043ef8290

Ich habe das gleiche Problem wie @otakustay erlebt
Es scheint unmöglich, kontrollierte Eingaben mit IME-Eingaben zu unterstützen. Ich habe die Abfolge der Ereignisse auf Folgendes zurückgeführt.

  1. Der Benutzer gibt einen Buchstaben ein, z. B. w
  2. onChange wird ausgelöst
  3. Der Status wird mit einem neuen Wert aktualisiert
  4. Neuer Wert wird auf das nach unten gesetzt input durch das value Attribut.
  5. Die IME "Komposition" wird an dieser Stelle unterbrochen

    • Das Eingabeelement enthält eine Zeichenfolge w

    • Im IME-Puffer ist außerdem eine separate Zeichenfolge w gespeichert

  6. Der Benutzer gibt einen anderen Buchstaben ein, z. B. a
  7. Die Zeichenfolge in der Eingabe a kombiniert mit der Zeichenfolge den IME-Puffer, um wwa zu erzeugen.
  8. Wiederholen Sie die Schritte 1 bis 7, um eine Reihe doppelter Zeichen zu erhalten.

Ich habe festgestellt, dass der Fehler nur auftritt, wenn die Eingabe nach dem nächsten Repaint > 15 ms nach dem KompositionUpdate-Ereignis erneut gerendert wird.

Im Moment besteht meine einzige Lösung darin, von gesteuerten Eingängen wegzuschalten.

Bearbeiten : Hier ist eine einfache Reproduktion: https://jsfiddle.net/kbhg3xna/
Edit2 : Hier ist meine hackige Problemumgehung: https://jsfiddle.net/m792qtys/ cc: @otakustay

Irgendwelche Updates dazu?

Update?

Gibt es hierzu Neuigkeiten?

Betäubt wurde ich mit dieser Frage konfrontiert

Interessant, sieht das Problem nicht nur um die mehrfache onChange. Wenn wir den Status nicht zwischen onCompositionStart und onCompositionEnd , "steuert" die Reaktion den Wert so wie er ist. Diese Aktion unterbricht die Komposition. Das heißt, wir werden das onCompositionEnd -Ereignis nicht erhalten ...... (Wenn ich falsch liege, erwähne mich bitte.) Aber wir können den Status nur sofort ändern (andernfalls müssen wir uns dem Problem stellen @ Knubie erwähnt). Eine Reproduktion hier (sieht aus wie eine "halbkontrollierte" Komponente): https://gist.github.com/cpdyj/6567437d96c315e9162778c8efdfb6e8

Aber ich bin so überrascht, dass das Problem während fünf Jahren nicht behoben werden kann 😢

@hellendag Ich denke, wir sollten onChange nicht auslösen, bis die IME-Zeichenfolge festgeschrieben ist.

Ich denke nicht, dass dies eine gültige Lösung ist, da eine Komponente möglicherweise die "nicht festgeschriebene" IME-Zeichenfolge kennen möchte, um beispielsweise Optionen in einer Liste zu filtern, während der Benutzer sie eingibt.

Ich bin nicht sicher, ob der Ansatz, den ich in diesem anderen Thread verwende, denjenigen helfen könnte, die dieses Problem lösen, aber hier ist ein Link für alle Fälle: https://github.com/facebook/react/issues/13104#issuecomment -691393940

irgendwelche Updates?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen