Was ist in React der Unterschied zwischen onChange und onInput?

89

Ich habe versucht, nach einer Antwort darauf zu suchen, aber die meisten von ihnen befinden sich außerhalb des Kontextes von React, onChangebei dem Unschärfe ausgelöst wird.

Bei der Durchführung verschiedener Tests kann ich nicht sagen, wie unterschiedlich diese beiden Ereignisse sind (wenn sie auf einen Textbereich angewendet werden). Kann jemand etwas Licht ins Dunkel bringen?

ffxsam
quelle
1
Ich habe meinen Beitrag bearbeitet, um klarer zu sein. Ich habe speziell über Textbereiche gesprochen, nicht über Optionsfelder oder Kontrollkästchen.
ffxsam
Das ist ziemlich falsch, React ist nicht nur JS. Und Ereignisse verhalten sich in einigen Fällen etwas anders (z. B. onChange). Und nein, das Einfügen von Text in einen Textbereich (in React) löst sowohl onChangeals auch aus onInput. Fühlen Sie sich frei, in einer Geige zu testen und Sie werden sehen.
ffxsam
Für <Eingabe> und <Textbereich> ersetzt onChange den integrierten Oninput-Ereignishandler des DOM und sollte im Allgemeinen anstelle von verwendet werden.
Roko C. Buljan
Ich nehme an, onChange ist die sicherere Wette. Ich habe sogar versucht, den Wert des Textbereichs programmgesteuert zu ändern, weil ich dachte, er onChangewürde vielleicht auslösen und onInputnicht, aber beide werden ausgelöst.
ffxsam
Ja, jetzt, nachdem ich ein paar React Docs durchgesehen habe, sehe ich, dass React einige Dinge wie jQuery macht, Ereignisse normalisiert und ja. onChange scheint ein bevorzugter Weg zu sein. Und ja. Reagieren ist nichts anderes als JS. Es gibt keine besondere Magie. Nur Regeln.
Roko C. Buljan

Antworten:

81

Es scheint keinen wirklichen Unterschied zu geben

Reagieren Sie aus irgendeinem Grund Listener für Component.onChangedas DOM- element.oninputEreignis. Siehe den Hinweis in den Dokumenten zu Formularen:

Reagieren Sie Dokumente - Formulare

Es gibt mehr Menschen, die von diesem Verhalten überrascht sind. Weitere Informationen finden Sie in diesem Problem im React Issue Tracker:

Dokumentieren Sie, wie sich onChange von React auf onInput # 3964 bezieht

Zitat aus den Kommentaren zu diesem Thema:

Ich verstehe nicht, warum React sich dafür entschieden hat, dass sich onChange so verhält wie onInput. Soweit ich das beurteilen kann, haben wir keine Möglichkeit, das alte onChange-Verhalten wiederherzustellen. Die Ärzte behaupten, es sei eine "Fehlbezeichnung", aber nicht wirklich, es wird ausgelöst, wenn sich etwas ändert, nur nicht, bis die Eingabe ebenfalls den Fokus verliert.

Zur Validierung möchten wir manchmal keine Validierungsfehler anzeigen, bis die Eingabe abgeschlossen ist. Oder vielleicht wollen wir einfach nicht bei jedem Tastendruck ein erneutes Rendern. Jetzt können Sie dies nur mit onBlur tun. Jetzt müssen wir auch überprüfen, ob sich der Wert manuell geändert hat.

Es ist keine so große Sache, aber es scheint mir, als hätte React ein nützliches Ereignis weggeworfen und ist vom Standardverhalten abgewichen, als es bereits ein Ereignis gab, das dies tut.

Ich stimme dem Kommentar zu 100% zu ... Aber ich denke, eine Änderung würde jetzt mehr Probleme bringen als lösen, da bereits so viel Code geschrieben wurde, der auf diesem Verhalten beruht.

React ist nicht Teil der offiziellen Web-API-Sammlung

Obwohl React auf JS aufbaut und eine enorme Akzeptanzrate aufweist, gibt es eine Technologie, mit der React eine ganze Reihe von Funktionen unter seiner eigenen (relativ kleinen) API verbirgt. Ein Bereich, in dem dies offensichtlich ist, befindet sich im Ereignissystem, in dem unter der Oberfläche viel los ist, was sich grundlegend vom Standard-DOM-Ereignissystem unterscheidet. Nicht nur in Bezug darauf, welche Ereignisse was tun, sondern auch in Bezug darauf, wann Daten in welcher Phase der Ereignisbehandlung bestehen bleiben dürfen. Mehr dazu lesen Sie hier:

Reagieren Sie auf das Ereignissystem

Stijn de Witt
quelle
1
Der letzte Absatz ist irreführend / unwahr.
Rounce
1
React ist kein Framework (wo bietet es Routing, Persistenz, Netzwerk-E / A-Verwaltung usw.?), Sondern eine Bibliothek, die die Kernabstraktion für die Bearbeitung von Anzeigebäumen über plattformspezifische Backends (React-Dom, React-Native, usw.).
Rounce
7
Wow OK. Ich stimme irgendwie zu, dass es eher eine Bibliothek als ein Framework ist, aber den Absatz deswegen irreführend / unwahr zu nennen? Ich bin auch nicht einverstanden mit der Vorstellung, dass ein Framework alle Aspekte einer Webanwendung bereitstellen sollte ... Es gibt beispielsweise Routing-Frameworks oder Dinge wie Redux, bei denen es sich um ein State-Management-Framework handelt. In meinen Augen können Sie mit einem Framework Teile einer funktionierenden Maschine ausfüllen. Bei Redux füllen Sie Reduzierungen aus. Bei Express füllen Sie Request Handler und Middleware aus. Aber die Unterscheidung ist gelinde gesagt eine Grauzone.
Stijn de Witt
4
stimme voll und ganz zu. Über die Unterscheidung zwischen Bibliothek und Framework zu streiten, ist wirklich Zeitverschwendung. hängt nur davon ab, auf welcher Abstraktionsebene Sie arbeiten.
Swyx
1
@chadsteele Danke Kumpel, schön zu hören, dass es dir geholfen hat
Stijn de Witt
23

Es gibt keinen Unterschied

React hat nicht das Verhalten des Standardereignisses 'onChange'. Das 'onChange', das wir in react sehen, hat das Verhalten des Standardereignisses 'onInput'. Um Ihre Frage zu beantworten, gibt es keinen Unterschied zwischen beiden. Ich habe auf GitHub ein Problem bezüglich derselben angesprochen, und dies ist, was sie dazu zu sagen haben:

Ich denke, dass zu dem Zeitpunkt, als diese Entscheidung getroffen wurde (vor ~ 4 Jahren?), OnInput nicht konsistent zwischen Browsern funktionierte und für Leute, die von anderen Plattformen ins Web kamen, verwirrend war, wie sie es von dem Ereignis „change“ erwarten würden Feuer bei jeder Veränderung. Im Falle von React ist dies ein größeres Problem, da die kontrollierten Eingaben niemals aktualisiert werden, wenn Sie Änderungen nicht früh genug verarbeiten, was dazu führt, dass die Leute glauben, React sei fehlerhaft. Also hat das Team es onChange genannt.

Rückblickend wäre es möglicherweise eine bessere Idee gewesen, onInput zu polyfillieren und seinen Namen beizubehalten, als das Verhalten eines anderen Ereignisses zu ändern. Aber dieses Schiff ist schon lange gesegelt. Wir werden diese Entscheidung vielleicht in Zukunft noch einmal überdenken, aber ich möchte Sie nur ermutigen, sie als eine Eigenart von React DOM zu behandeln (an die Sie sich ziemlich schnell gewöhnen werden).

https://github.com/facebook/react/issues/9567

Auch dieser Artikel bietet mehr Einblick. Als Problemumgehung für das Fehlen von "onChange" schlägt der Artikel vor, das Ereignis "onBlur" anzuhören.

https://www.peterbe.com/plog/onchange-in-reactjs

Nikhil Goyal
quelle
Ich bin anscheinend auf einen Unterschied gestoßen. OnChange von React wird nicht ausgelöst, wenn ein Zeichen ausgewählt und durch dasselbe Zeichen ersetzt wird. OnInput wird ausgelöst.
Per Enström vor
3

Kürzlich habe ich einen Fehler bekommen, bei dem onChangedas Kopieren und Einfügen in das Eingabefeld von IE11 nicht möglich war. Während das onInputEreignis dieses Verhalten erlauben würde. Ich konnte keine Dokumentation finden, die dies in den Dokumenten beschreiben würde, aber das zeigt, dass es einen Unterschied zwischen den beiden gibt (erwartet oder nicht).

Alan Souza
quelle
2

Wie Sie in verschiedenen Kommentaren hier sehen können, behandelt React onChange und onInput gleich und so, anstatt die Vorzüge dieser Entscheidung zu diskutieren. Hier ist die Lösung.

Verwenden Sie onBlur, wenn Sie die Änderungen des Benutzers erst verarbeiten möchten, wenn sie abgeschlossen sind. :) :)

Chad Steele
quelle
1

Für alle, die über dieses Problem gestolpert sind und nach einer Möglichkeit suchen, auf das tatsächliche, DOM-basierte changeEreignis zu hören, habe ich es so gemacht (geschrieben in TypeScript):

import { Component, createElement, InputHTMLAttributes } from 'react';

export interface CustomInputProps {
    onChange?: (event: Event) => void;
    onInput?: (event: Event) => void;
}

/**
 * This component restores the 'onChange' and 'onInput' behavior of JavaScript.
 *
 * See:
 * - https://reactjs.org/docs/dom-elements.html#onchange
 * - https://github.com/facebook/react/issues/3964
 * - https://github.com/facebook/react/issues/9657
 * - https://github.com/facebook/react/issues/14857
 */
export class CustomInput extends Component<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'ref'> & CustomInputProps> {
    private readonly registerCallbacks  = (element: HTMLInputElement | null) => {
        if (element) {
            element.onchange = this.props.onChange ? this.props.onChange : null;
            element.oninput = this.props.onInput ? this.props.onInput : null;
        }
    };

    public render() {
        return <input ref={this.registerCallbacks} {...this.props} onChange={undefined} onInput={undefined} />;
    }
}

Bitte lassen Sie mich wissen, wenn Sie Möglichkeiten zur Verbesserung dieses Ansatzes oder Probleme damit sehen. Im Gegensatz dazu blurwird das changeEreignis auch ausgelöst, wenn der Benutzer die Eingabetaste drückt, und wird nur ausgelöst, wenn sich der Wert tatsächlich geändert hat.

Ich sammle immer noch Erfahrungen mit dieser CustomInputKomponente. Zum Beispiel verhalten sich Kontrollkästchen seltsam. Ich muss entweder event.target.checkedim onChangeHandler invertieren, während ich den Wert an das Kontrollkästchen mit übergebe, checkedoder diese Inversion entfernen, wenn ich den Wert an das Kontrollkästchen mit übergebe, defaultCheckedaber dies führt dazu, dass mehrere Kontrollkästchen, die denselben Status an verschiedenen Stellen auf der Seite darstellen, synchron bleiben . (In beiden Fällen habe ich keinen onInputHandler an die CustomInputKontrollkästchen für übergeben.)

Kaspar Etter
quelle
0

Ein Unterschied scheint zu sein, dass onChangebeim Auswählen und Ersetzen eines Zeichens durch dasselbe Zeichen nicht ausgelöst wird, solange dies der Fall onInputist.

Siehe diese Sandbox: https://codesandbox.io/s/react-onchange-vs-oninput-coggf?file=/src/App.js

  • Geben Sie "A" in das Feld ein, wählen Sie dann alle aus und geben Sie "B" ein. Dies löst 4 Ereignisse aus, 2 onChangeund 2 onInput.
  • Wählen Sie nun alle aus und geben Sie erneut "B" ein, bis ein neues onInputEreignis ausgelöst wird , aber nein onChange.
Per Enström
quelle