React: Bieten Sie eine Möglichkeit, vom Browser automatisch ausgefüllte Formularwerte für kontrollierte Komponenten zu verarbeiten

Erstellt am 22. Feb. 2014  ·  80Kommentare  ·  Quelle: facebook/react

Wenn es eine kontrollierte Komponente für Formularnamen gibt, die der Benutzer in seinem Browser gespeichert hat (wie bei Benutzernamen- / Kennwortfeldern üblich), rendert der Browser die Seite manchmal mit Werten in diesen Feldern, ohne onChange-Ereignisse auszulösen. Wenn der Benutzer das Formular sendet, spiegelt der Komponentenstatus nicht wider, was dem Benutzer angezeigt wird.

Beim Experimentieren scheint es, dass die Daten beim Laden vorhanden sind (getestet durch Protokollieren des Wertes this.refs.myinput.getDOMNode ().)

DOM Bug

Hilfreichster Kommentar

Haben Sie versucht, das Attribut 'name' für die Eingabe zu definieren? Für mich geht das. Der onChange wird beim automatischen Ausfüllen des Benutzers ausgelöst

Alle 80 Kommentare

Dies scheint etwas mehr zu diskutieren: http://stackoverflow.com/a/11710295

cc mich

( @visionscaper Tipp: Drücken Sie in der rechten Spalte auf "Abonnieren".)

Irgendwelche Updates oder empfohlenen Best Practices zu diesem Thema? Die Polyfill für das automatische Ausfüllen von Ereignissen scheint eine Vorschlaghammerlösung zu sein.

Safari (8) löst Änderungsereignisse beim automatischen Ausfüllen aus, sprudelt jedoch nicht, sodass sie den Reaktionshandler nicht erreichen.

Eine verwandte Diskussion unter https://github.com/angular/angular.js/issues/1460 wurde mit einigen Vorschlägen abgeschlossen, von denen einer https://github.com/tbosch/autofill-event zum Feuern verwendet Ändern Sie das Ereignis beim automatischen Ausfüllen manuell.

Ich denke, wir können auch hier schließen.

Es wäre schön, das AutoFill-Event als Teil von React als Addon zu haben. Diese Funktionalität wird für praktisch jeden erforderlich sein, der React zur Formularvalidierung verwendet. Das AutoFill-Event-Skript fügt außerdem eine Abhängigkeit für jQuery hinzu, die in vielen Fällen unerwünscht sein kann.

Dies ist ein Browser-Fehler, der alle Browser etwas anders betrifft. Ich denke, nur weil Winkel beim Versuch, herumzuarbeiten oder zu reparieren, nicht bedeutet, dass man reagieren sollte. Es ist eine häufige Sache, aber ich verstehe, ob dies ein "Wontfix" ist.

Ich bin nicht besonders gut mit den Bug-Trackern der verschiedenen Browser vertraut, aber es wäre schön, wenn jemand, der dies tut, Probleme dafür finden oder öffnen könnte. Ich denke, das Reaktionsteam hat mehr Gewicht als die meisten Benutzer, wenn sie ein Problem damit eröffnen. Und wir könnten hier die Tickets für die interessierten Reaktionsentwickler abholen.

Ich holte den eckigen Faden ein. Firefox hat Probleme mit Passwortfeldern (https://bugzilla.mozilla.org/show_bug.cgi?id=950510 ist noch offen), kein Wort zu Safari's Bug #, Chrome ist behoben.

An einigen Stellen werden bereits Probleme verfolgt - https://github.com/angular/angular.js/issues/1460#issuecomment -53947546

Das Chrome-Problem ist jetzt geschlossen, funktioniert aber in Chrome 50 mit React 0.14.8 eindeutig nicht.

Noch kein Fix?

Ich habe das Gefühl, dass dies eine Weile funktioniert hat und vor kurzem wieder kaputt gegangen ist?

Gibt es ein Update zu diesem Thema?

Hier ein Auszug meiner Lösung für dieses Problem:

export default class Input extends Component {
  static propTypes = {
    value: PropTypes.string,
    onFieldChange: PropTypes.func,
  };

  static defaultProps = {
    value: '',
  }

  componentDidMount() {
    this._listener = setInterval(() => {
      if (!this.input || this._previousValue === this.input.value) {
        return;
      }

      this._previousValue = this.input.value;

      const evt = document.createEvent('HTMLEvents');
      evt.initEvent('input', true, true);
      this.input.dispatchEvent(evt);
    }, 20);
  }

  componentWillUnmount() {
    clearInterval(this._listener);
  }

  refInput = (input) => this.input = input;

  render() {
    const { label,
      value,
      onFieldChange,
    } = this.props;

    this.input = this.input || { value };

    return (
        <input
            value={this.input.value}
            onChange={onFieldChange}
            ref={this.refInput}
        />
    );
  }
}

HINWEIS: value stammt aus dem Status und onFieldChange aktualisiert den Status mit dem neuen Wert

Der setInterval-Code stammt von https://github.com/Pephers/react-autofill

Kann jemand bestätigen, dass dieses Problem mit iOS 10.2 behoben wurde? Ich kann es jetzt nicht reproduzieren ...

Ich habe immer noch Probleme unter iOS 10.2 mit Chrome Version 55.0.2883.79 ... Im Gegensatz zu dem, was oben beschrieben wurde, blinkt der automatisch ausgefüllte Inhalt für mich kurz im Formular und wird dann wieder entfernt.
Es stimmt also jetzt mit dem überein, was im Status gespeichert ist. Das automatische Ausfüllen funktioniert jedoch immer noch nicht ...

Ich reproduziere das gleiche Problem, auf das @irisSchaffer gestoßen ist. Ich habe eine isomorphe Anwendung, in der ich eine statische Seite mit Reagieren und Ausdrücken rendere. Dann exportiere ich auf dem Client die Requisiten und verwende dieselbe Seitenkomponente.

Selbst wenn der Kennworteingabewert nicht durch "Reagieren" behandelt wird, löscht die Client-Reaktionskomponente das gespeicherte Kennwort aus der Eingabe, auch wenn Chrome es kurz anzeigt. Wenn ich Javascript im Browser deaktiviere, bleibt das gespeicherte Passwort an seiner Stelle.

Dieses Problem ist nur in Chrome mit der letzten Version 58 sichtbar.

Das gespeicherte Passwort ist über element.value nicht zugänglich, bis ein Ereignis auf dem Dom ausgelöst wird, z. B. der Fokus, ein Schlüsselereignis usw. Es wurde versucht, ein Ereignis durch Javascript zu simulieren, ohne dass der Wert ausgefüllt werden muss Eigentum.

+1. irgendwelche Fixes oder Hacks?

Ich bin immer noch mit diesem Problem unter iOS 10.3.3 Chrome 60.0.3112.89 konfrontiert.

Das automatische Ausfüllen funktioniert, füllt das Feld, ändert aber nicht den Status.

Umgehung des Dekorateurs: https://github.com/Pephers/react-autofill

Allgemeine Komponentenumgehung:

/**
  Trigger onChange event after browser auto-fill.

  <strong i="8">@see</strong> https://github.com/facebook/react/issues/1159
  <strong i="9">@example</strong> <AutoFillWatch component={ref =>
    <input required type="password" ref={ref} />
  }/>
*/
class AutoFillWatch extends Component {
  static propTypes = {
    // Auto-fill component like: <input type="password"
    component: PropTypes.func.isRequired,

    // component pass-through reference
    ref: PropTypes.func,
  }

  componentDidMount() {
    this._listener = setInterval(() => {
      if (!this.input || this._previousValue === this.input.value) {
        return;
      }

      this._previousValue = this.input.value;

      const evt = document.createEvent('HTMLEvents');
      evt.initEvent('input', true, true);
      this.input.dispatchEvent(evt);
    }, 100);
  }

  componentWillUnmount() {
    clearInterval(this._listener);
  }

  componentDidMount() {
    const {ref} = this.props
    if(ref) {
      console.log('ref', this.input);
      ref(this.input)
    }
  }

  refInput = (input) => this.input = input;

  render() {
    const {component} = this.props
    return component(this.refInput)
  }
}

Chrome für iOS (stellen Sie sicher, dass Sie mit dem automatischen Ausfüllen von Chrome testen und nicht mit den Vorschlägen der iOS-Tastatur) gibt nur beim automatischen Ausfüllen von Werten change . Mobile Safari hingegen gibt focus , keydown , input , keyup , change und blur aus macht Chrome und Safari auf Mac.

React verwendet kein change -Ereignis für reguläre <input /> was die Hauptursache für dieses Problem zu sein scheint: https://github.com/facebook/react/blob/e932ad68bed656eed5295b61ba74e5d0857902ed/src/renderers /dom/shared/eventPlugins/ChangeEventPlugin.js#L66 -L71

Wäre es nicht möglich, dass React onChange auch bei DOM change -Ereignissen ausgelöst wird? Würde das schaden?

Zugehöriges Problem für Chrome iOS: https://bugs.chromium.org/p/chromium/issues/detail?id=705275

Ich habe das automatische Ausfüllen und Ereignisse mit der folgenden kleinen Seite getestet:

<html>

<head>
  <script type="text/javascript">
    window.onload = function () {
      let elements = document.querySelectorAll('input');
      let actions = document.getElementById('actions')
      let events = 'focus blur keydown keyup change input'.split(' ');

      elements.forEach(element => {
        events.forEach(event => {
          element.addEventListener(event, e => {
            console.log(e);
            let eTypeNode = document.createTextNode(element.name + ' > ' + e.type + ":" + e.code + ":" + e.keyIdentifier);
            actions.appendChild(eTypeNode);
            actions.appendChild(document.createElement('br'));
          })
        })
      })
    };
  </script>
</head>

<body>
  <form>
    <input type="text" name="name" id="a" autocomplete="name" />
    <input type="email" name="email" id="b" autocomplete="email" />
    <input type="tel" name="tel" id="c" autocomplete="tel" />
  </form>
  <div id="actions"></div>
</body>

</html>

Das Änderungsereignis wird in Chrome v62 ausgegeben, wenn Sie Eingaben mit einem <form /> -Element umschließen.

Es gibt einen onInput-Ereignishandler, der den Wert eines Eingabefelds abruft, wenn er sich ändert.

Hier wird immer noch ein ungewöhnliches Verhalten beim automatischen Ausfüllen unter iOS festgestellt. Der obige Dekorator für das automatische Ausfüllen von Reaktionen scheint mit dem einfachen automatischen Ausfüllen gut zu funktionieren, nicht jedoch mit den von der Tastatur bereitgestellten Verknüpfungen zum automatischen Ausfüllen.

Dies sollte jetzt in Chrome für iOS behoben sein: https://chromium.googlesource.com/chromium/src/+/55518e17850cac0bdc6fca7b24092bea479e34db. Ich bin mir nicht sicher, wann dieser Patch in einer veröffentlichten Version enthalten sein wird.

Warum muss onChange verwendet werden?
Warum MÜSSEN wir 'onChange' verwenden, aber nicht das 'change event'?

class Input extends Component {
    componentDidMount(){
        this.input.addEventListener('change', (e)=>{
            this.props.onChange(this.props.field, e.target.value)
        })
    }
    render(){
        const { className, name, label, autofill, field, onBlur, onChange, value, error, visited, required, type, maxLength } = this.props
        return (
            <div className={ [styles.inputWrap, className || ''].join(' ') } onBlur={e => onBlur(field)}>
                <input ref={n => this.input = n} id={field} name={name || field} type={ type || 'text' } defaultValue={ value }
                 autoComplete={ autofill } maxLength={maxLength} />
                <div className={ [styles.placeholder, value? styles.active:''].join(' ') }>
                    <FormattedMessage id={label} />
                    <i className={styles.required}>{required? '*':''}</i>
                    <span className={ styles.error }>{ visited? error:'' }</span>
                </div>
            </div>
        )
    }
}

Das Änderungsereignis wird in Chrome v62 ausgegeben, wenn Sie Eingaben mit einem <form /> -Element umschließen.

Ich bestätige, dass diese Lösung für Chrome zum automatischen Ausfüllen von Telefonnummern über autoComplete="tel" funktioniert
https://github.com/catamphetamine/react-phone-number-input/issues/101

Die oben genannten Lösungen mit this._previousValue !== this.input.value funktionieren leider nur für iOS Safari. Das .value iOS Chrome ist nach dem automatischen Ausfüllen noch leer.

Ich habe keine Ahnung, wie Leute mit dem automatischen Ausfüllen von Formularen umgegangen sind, wenn sie kontrollierte Komponenten verwendet haben. Betrachten Sie dieses Anmeldeszenario:

  • autoFill email: Auch beim dispatchEvent-Hack ändert Chrome nichts. Die E-Mail .value als leer gemeldet
  • Schreiben Sie einen Wert in das Kennwortfeld: Die E-Mail geht verloren, weil der React-Status denkt, dass sie leer ist

Sofern es keine Möglichkeit gibt, Chrome dazu zu bringen, den Wert zu melden, kann ich mir keine andere Lösung vorstellen als die Verwendung unkontrollierter Komponenten, die Validierung von HTML5-Eingaben und das Abrufen von Formularwerten beim Senden wie früher.

Sie können das Problem hier verfolgen (und markieren): https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Ich konnte die obige Lösung auch nicht für @DominicTobias verwenden. Es gibt mehrere Ebenen von Problemen. Das erste war, dass this.input.value immer leer zurückkam. Ich habe jedoch festgestellt, dass Sie einen Wert zurückerhalten, wenn Sie in jeder Schleife document.getElementById , dann document.getElementById(id).value .

Dies löst das dispatchEvent -Problem nicht, aber zumindest können Sie den automatisch ausgefüllten Wert abrufen und damit arbeiten (z. B. nur den onChange -Handler einer kontrollierten Eingabe aufrufen).

@wlingke gut zu wissen (und wie seltsam)! Ich muss auch diesen Weg gehen, wenn sie den Fehler nicht rechtzeitig vor meiner Veröffentlichung beheben

@wlingke Als ich eine Demo für die Chrome-Leute onChange ist ein synthetisches Ereignis in React, bei dem das Ereignis change , was mir ziemlich seltsam erscheint.

Sie können sogar in der Demo unten sehen, dass es sich anders verhält, eher so, als würde es auf ein input -Ereignis warten. Wenn Sie das echte change -Ereignis verwenden, funktioniert es in iOS Chrome ordnungsgemäß.

Daher würde ich vorschlagen, einen Verweis auf das Element zu erhalten und nur das eigentliche Änderungsereignis sowie das onChange -Ereignis anzuhören, das das input -Ereignis zu sein scheint, wenn Sie den Status als das aktualisieren müssen Benutzer tippt.

Demo: https://kind-stallman-f3c045.netlify.com/

@DominicTobias Ich habe zuvor sowohl change als auch input Ereignisse einzeln sowie beide gleichzeitig in diesem Dekorateur ausprobiert, konnte es aber in meiner App nicht zum Laufen bringen.

Ich bin mir auch nicht sicher, ob sich dadurch etwas ändert. Aber es gibt einen Unterschied zwischen dem automatischen Ausfüllen eines Feldes und dem automatischen Ausfüllen mehrerer Felder. Das input -Ereignis funktionierte einwandfrei, wenn ein Feld automatisch ausgefüllt wurde. In Mobile Chrome können Sie jedoch eine Reihe von Feldern gleichzeitig automatisch über die Tastatur ausfüllen (z. B. Vorname, Nachname, E-Mail-Adresse mit einem Fingertipp).

In diesem zweiten Szenario lässt der Dekorateur das erste Feld ordnungsgemäß automatisch ausfüllen (erstes Feld bedeutet das Feld, das derzeit scharfgestellt ist). Der Dekorateur (der an alle drei Felder angehängt ist) scheint jedoch nicht an den anderen Feldern zu arbeiten.

@wlingke Interessant, ich habe einige weitere Felder hinzugefügt, aber wenn ich alle drei Felder gleichzeitig in iOS Chrome automatisch

screen shot 2018-03-08 at 19 29 15

(Der Screenshot stammt vom Desktop-Browser, aber ich erhalte auf meinem Telefon das gleiche Ergebnis.)

@DominicTobias Ich denke, wenn Sie das input -Ereignis verwenden - was ich zuvor verwendet habe, funktioniert es vollständig in Desktop. Und arbeiten Sie für die erste Eingabe in Mobile.

input Ereignis ist dem onChange Reaktion am nächsten. Das change -Ereignis wird nur dann gespeichert, wenn ein Element nach meinem Verständnis den Fokus verliert (https://stackoverflow.com/questions/17047497/what-is-the-difference-between-change-and-input-event-). für ein Eingabeelement)

Yep react hat aus irgendeinem Grund onChange to input event: https://stackoverflow.com/questions/38256332/in-react-whats-the-difference-between-onchange-and-oninput

Um die Dinge einfach zu halten, nenne ich es einfach auch in meiner Input -Komponente für tatsächliche Änderungsereignisse (sowie die normalen Eingabeereignisse). Jetzt funktioniert es in iOS Chrome. Probieren Sie es aus und lassen Sie es mich wissen!

componentDidMount() {
  this.inputRef.addEventListener('change', this.onChange);
}

onChange = (event) => {
  // React actually uses the input even for onChange, this causes autofill to
  // break in iOS Chrome as it only fires a change event.
  if (this.props.onChange) {
    this.props.onChange(event);
  }
}

componentWillUnount() {
  this.inputRef.removeEventListener('change', this.onChange);
}

Bearbeiten: Chrome soll in v65 behoben sein, aber die Leute berichten, dass es immer noch nicht funktioniert: /

Danke für die Erklärung Dominic. Wir haben dieses Verhalten bereits im Dezember behoben. Wir lösen jetzt Keydown-, Änderungs-, Eingabe- und Keyup-Ereignisse aus.
https://chromium-review.googlesource.com/c/chromium/src/+/771674

Wir hatten auch eine Lösung für React.
https://chromium-review.googlesource.com/c/chromium/src/+/844324

Dies behebt zwar das Verhalten beim automatischen Ausfüllen, ruft jedoch den onChange-Handler nicht auf.

Ich habe auch ein Problem dazu angesprochen und der Entwickler war sich sicher, dass es in 65 behoben werden würde ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Ich höre auch das native change -Ereignis wie onChange redux-form im nativen Ereignis-Listener aus, der an mount angehängt ist.

Ich benutze auch den input:-webkit-autofill Selektor für das Styling.

Überzeugen Sie sich selbst unter https://labrewlangerie.com (Kontaktformular).

Scheint, als ob dieses Update endlich auf dem Weg zu Chrome iOS ist! Ich bin mir jedoch nicht sicher, in welcher Version, da diese am 1. Dezember zusammengeführt worden zu sein scheint.

https://bugs.chromium.org/p/chromium/issues/detail?id=705275#c11
https://chromium-review.googlesource.com/c/chromium/src/+/771674

Gleiches hier in Chrome 65, Reagieren Sie 15.6.

Das ist eine Schande, Mahmadi sagte, dass es am 13. März auf v65 gehen würde :(

Kommentar 15 von [email protected] , 9. März
Das Update ist nicht in Chrome 64. Mein schlechtes. Chrome 65 muss (wird ab dem 13. März eingeführt). Ich habe gerade Ihre Demo-Website für native Ereignisse getestet und sie funktioniert unter Chrome 65. Ich freue mich, dass Sie dies weiterverfolgen.

https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Versuchen Sie, hier auf Ihrem Telefon zu gehen und zu überprüfen: https://kind-stallman-f3c045.netlify.com/native.html

Was wirklich seltsam ist, ist, dass es in v65 nativ funktioniert, aber obwohl es eine Eingabe erhält, wird es in React nicht empfangen! Benötigen Sie weitere Untersuchungen? Ich bin mir nicht ganz sicher, wie der Handler reagiert (oder ob er auf dem Dokumentelement ausgeführt wird, wie z. B. ein Klick-Handler).

Nativ kann ich sehen, dass das Eingabeereignis jetzt stattfindet (https://kind-stallman-f3c045.netlify.com/native.html):

native

Aber irgendwie erhält React keines dieser Ereignisse (https://kind-stallman-f3c045.netlify.com):

react

add onBlur = {this.handleChange} bei der Eingabe

Das KlarnaUI-Team hat einen interessanten Hack, um dieses Problem zu lösen, indem es das onAnimationStart -Ereignis und die :-webkit-autofill -Pseudoklasse ausnutzt, wie in diesem Artikel beschrieben - https://medium.com/@brunn/detecting -autofilled- Felder-in-Javascript-aed598d25da7

Wir haben diesen Hack in unseren Anwendungen verwendet, er funktioniert einwandfrei (konnte nur auf Chrome getestet werden). Ich werde versuchen, mit dieser Technik eine Unterlegscheibe zu entwickeln, damit sie generisch ist.

Irgendwelche Updates zu diesem Problem?

Was ist der beste Trick für den Moment?

@ericflo @sophiebits

Dieses Problem scheint immer noch zu bestehen, irgendwelche Updates?

@Pixelatex @Aarbel siehe meine Antwort etwas weiter oben - https://github.com/facebook/react/issues/1159#issuecomment -371604044

Grundsätzlich lauscht React auf das input -Ereignis und nicht auf das change one-Ereignis für onChange, sodass diese Antwort nur auf beide hört.

@DominicTobias Ich habe es versucht, aber wir müssen irgendwo auf der Seite einen tatsächlichen Klick haben, damit dies funktioniert. Die Veranstaltung wird bis dahin nicht registriert.

Ich habe jetzt seit ungefähr einem Tag mit dem Thema zu kämpfen. Ich kann definitiv auflisten, was in Desktop Chrome 67 und React 15.6.0 NICHT funktioniert:

  1. onAnimationStart mit input:-webkit-autofill https://medium.com/@brunn/detecting -autofilled-fields-in-javascript-aed598d25da7 - wird vorzeitig ausgelöst (das Formular ist noch nicht ausgefüllt)
  2. this.inputRef.addEventListener("transitionend", this.doSomething, false) in Kombination mit input:-webkit-autofill css-Übergang - wird pünktlich ausgelöst, aber Sie können die Seite nicht @Pixelatex erwähnt hat
  3. this.inputRef.addEventListener("change", this.doSomething) - wird erst ausgelöst, wenn Sie auf die Seite klicken
  4. onBlur={this.doSomething} - löst kein Ereignis aus

Auch diese Lösungen funktionieren leider NICHT. Der HTML-Code enthält den automatisch ausgefüllten Wert nur, wenn Sie die Seite anstoßen. Die nächstgelegene ist 2, da Sie document in die Konsole eingeben können und die Seite aktiviert wird. Bisher hat dies programmgesteuert nicht funktioniert.
@DominicTobias Funktioniert Ihre Lösung auf Desktop Chrome?

Eigentlich habe ich einen dreckigen Hack. Wenn Sie Lösung 2 aus dem vorherigen Kommentar verwenden, können Sie sich auf [hier kommt Schmutzigkeit] "Gespeicherte Formulardaten sind gültige Daten" verlassen. Anschließend können Sie den Übergang nach Abschluss des Ereignisses zum automatischen Ausfüllen abfangen und beispielsweise die Schaltfläche Senden aktivieren. Hier ist wie:

CSS:

input:-webkit-autofill {
    transition: background-color 0.1s ease-in-out 0s;
}

im Konstruktor:

this.autofillCompleted = this.autofillCompleted.bind(this)

Innerhalb Ihrer React Component-Klasse:

componentDidMount(){
if(this.myInputRef)
      this.myInputRef.addEventListener("transitionend", this.autofillCompleted, false)
}
autofillCompleted(){
    this.setState({ submitActive: true });
}
componentWillUnmount(){
    if(this.myInputRef)
      this.myInputRef.removeEventListener("transitionend", this.autofillCompleted, false)
}

In JSX:

<FormControl
            inputRef={(node) => this.myInputRef= node}
/>

PS: Verwenden Sie für grundlegende Komponenten (wie input ) ref prop anstelle von inputRef

In der neuesten Chrome Desktop- und iOS 12-Safari führt das Umschließen von Elementen in <form> , dass die automatische Vervollständigung ein onChange-Ereignis auslöst.

@rxb in <p> </p> einwickeln?

@basarat Entschuldigung, ich habe meinen Code-Markdown vergessen und das Tag ist verschwunden ... <form> tag

Gibt es ein Update zu diesem Thema?

Gibt es ein Update zu diesem Thema?

Wenn es Updates gäbe, wären sie zu diesem Thema.

Bitte posten Sie nicht, wenn Sie nichts Sinnvolles hinzuzufügen haben - Sie spammen jeden, der dieses Problem abonniert hat. Vielen Dank.

Ich habe auch ein Problem dazu angesprochen und der Entwickler war sich sicher, dass es in 65 behoben werden würde ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Dieser Fix wurde leider nicht mit dem React-Team koordiniert. Uns war nicht bekannt, dass Chrome unter iOS jetzt eine Eigenschaft festlegt, die in früheren Versionen versehentlich den Änderungshandler ausgelöst hat. Wir hatten nicht die Absicht, dies zu unterstützen - und wir haben bereits eine Änderung vorgenommen, durch die das Verhalten beseitigt wurde (wir waren uns nicht bewusst, dass Chrome sich darauf verlassen hat).

Wenn Sie an einem Browser arbeiten und einen reaktionsspezifischen Hack hinzufügen, stellen Sie sicher, dass Sie jemanden aus dem React-Team einschleifen.

Kann jemand dies auf den aktuellen Fehler reduzieren. React behandelt BEIDE change und input Ereignisse für Eingaben. Wenn das automatische Ausfüllen eines der beiden auslöst, sollte es funktionieren. Es ist also nicht klar, dass das ursprüngliche Problem hier immer noch relevant ist. ODER es gibt hier einige Dinge, die unterschiedliche Probleme haben können

  • Die Werte werden vor dem "Rendern" automatisch ausgefüllt, z. B. gab es eine SSR-Seite, deren Reaktion hydratisiert. Ich glaube, wir verwenden in diesem Fall den richtigen Wert (cc @nhunzaker)
  • Eingaben lösen beim automatischen Ausfüllen keine Ereignisse aus
  • Eingaben lösen verschiedene Ereignisse aus, auf die React wartet (dies sollte ab Version 15 behoben sein).

Gibt es etwas, das ich hier verpasst habe, und weiß jemand, welche Browser sich richtig verhalten oder nicht?

Übrigens wollen wir dies als Teil von # 9657 betrachten - idealerweise sollte alles, was wir dort tun, teilweise dazu beitragen, dieses Problem zu lösen.

@jquense Wir verwenden den richtigen Wert, senden jedoch kein Änderungsereignis:

http://react-hydration.surge.sh/hydration

  1. Deaktivieren Sie "Auto-Hydrat"
  2. Ändern Sie den Wert
  3. Klicken Sie auf Hydrat
  4. Keine Änderung :(

ok, ich habe auch ein bisschen recherchiert:

Ich denke, hier gibt es zwei Probleme:

  • Werte, die vom Browser eingegeben werden, bevor Hydrate reagieren, gehen verloren.
  • Chrome unter IOS löst beim automatischen Ausfüllen keine Ereignisse aus

Hier ist eine Site, die Sie zum Testen verwenden können: https://jquense.github.io/browser-test-pages/autofill/login/

Soweit ich weiß, funktionieren alle anderen Plattformen und Browser einwandfrei für die Auswahl automatisch ausgefüllter Werte

Beachten Sie, dass es sich bei der obigen Seite um eine Gatsby-Seite handelt, sodass auch das SSR-Problem demonstriert wird

@nhunzaker Sie haben clevere Ideen zum IOS- https://github.com/vuejs/vue/issues/7058 gestoßen

React macht die automatische Vervollständigung nicht deaktiviert

Ich habe einen neuen Chrome-Fehler für das Chrome unter iOS-Problem gemeldet :

Haben Sie versucht, das Attribut 'name' für die Eingabe zu definieren? Für mich geht das. Der onChange wird beim automatischen Ausfüllen des Benutzers ausgelöst

@eatsjobs Wir verwenden attr name, haben aber das gleiche Problem.

Ich habe getestet

$$(':-webkit-autofill')

Funktioniert auf Chrome 70 und gibt automatisch ausgefüllte Eingänge zurück.

@QuantumInformation für mich gleich :(

handleOnChange = e => {
  this.setState({ email: e.target.value }, () => {
    alert(this.state.email)
  })
}
<form>
  <input
    name="email"
    type="email"
    placeholder="Enter Your Email"
    autocomplete="email"
    value={this.state.email}
    onChange={e => this.handleOnChange(e)}
   />
</form>

Ich versuche es so, sehe aus, als würde alles gut funktionieren.
Beim automatischen Ausfüllen wurde mein Status korrekt eingestellt. (ios 12)

Für diejenigen, die kürzlich auf dieses Problem gestoßen sind, wird es absichtlich von Browsern verursacht, um Sicherheitsrisiken zu vermeiden.

Wenn wir nach dem Laden der Seite auf automatisch ausgefüllte Werte zugreifen können, ist es sehr einfach, schädlichen Code zu schreiben, um Informationen in ein für Phishing bestimmtes Formular zu extrahieren. Geben Sie dem Benutzer keine Chance zu reagieren. Wahrscheinlich ein Teil des Grundes, warum autocomplete="off" von Browsern ignoriert wird.

Um dieses Problem zu lösen, müssen wir:

  1. Akzeptieren Sie die Tatsache, dass wir beim Bereitstellen des DOM-Knotens keinen Zugriff auf automatisch ausgefüllte Werte haben (und dies auch nie tun werden)
  2. Umfassen Sie die Sicherheitsbedenken, die von den Browsern aufgeworfen werden

Um dieses Problem zu lösen, denken Sie daran, wie Formulare ursprünglich entworfen wurden und verwendet werden sollen. Wenn der Benutzer auf ein <button type="submit" /> in einem <form> klickt, heißt es im Grunde "Hey, diese Aktion ist vom Benutzer beabsichtigt, jetzt wollen wir die Formularwerte auswerten".

Betrachten Sie dieses Beispiel einer wirklich einfachen SignInForm, die in React geschrieben wurde:

import React from 'react';

class SignInForm extends React.Component {
  constructor() {
    this.state = {
      email: '',
      password: '',
    };

    this.handleEmail = this.handleEmail.bind(this);
    this.handlePassword = this.handlePassword.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleEmail(event) {
    this.setState({ email: event.target.value });
  }

  handlePassword(event) {
    this.setState({ password: event.target.value });
  }

  handleSubmit() {
   console.log(this.state.email); // The email value
   console.log(this.state.password); // The password value
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
         <input
            name="email"
            type="text"
            value={this.state.email}
            onChange={this.handleEmail}
            placeholder="Email"
          />
         <input
            name="password"
            type="text"
            value={this.state.password}
            onChange={this.handlePassword}
            placeholder="Password"
          />
          <button type="submit" onClick={this.handleSubmit}>Sign In</button>
        </form>
    );
  }
}

export default SignInForm;

Nach dem Absenden aktualisiert und bewertet das Formular die Eingabefelder entsprechend.

Das heisst:

  1. Wir können die Schaltfläche "Senden" überhaupt nicht deaktivieren
  2. Die gesamte Validierung muss erfolgen, sobald der Benutzer auf diese Schaltfläche klickt

Meiner Meinung nach ist dies der pragmatischste Ansatz und erspart viel Kopfschmerzen. Ich hoffe, das hilft anderen in Zukunft.

Bearbeiten: Für diejenigen, die mit React nicht vertraut sind, können Sie unter diesem Link eine grundlegende Implementierung eines Formulars und einige zusätzliche wichtige Informationen finden: https://html.spec.whatwg.org/multipage/forms.html

Für diejenigen, die kürzlich auf dieses Problem gestoßen sind, wird es absichtlich von Browsern verursacht, um Sicherheitsrisiken zu vermeiden.

Wenn wir nach dem Laden der Seite auf automatisch ausgefüllte Werte zugreifen können, ist es sehr einfach, schädlichen Code zu schreiben, um Informationen in ein für Phishing bestimmtes Formular zu extrahieren. Geben Sie dem Benutzer keine Chance zu reagieren. Wahrscheinlich ein Teil des Grundes, warum autocomplete="off" von Browsern ignoriert wird.

Um dieses Problem zu lösen, müssen wir:

  1. Akzeptieren Sie die Tatsache, dass wir beim Bereitstellen des DOM-Knotens keinen Zugriff auf automatisch ausgefüllte Werte haben (und dies auch nie tun werden)
  2. Umfassen Sie die Sicherheitsbedenken, die von den Browsern aufgeworfen werden

Um dieses Problem zu lösen, denken Sie daran, wie Formulare ursprünglich entworfen wurden und verwendet werden sollen. Wenn der Benutzer auf ein <button type="submit" /> in einem <form> klickt, heißt es im Grunde "Hey, diese Aktion ist vom Benutzer beabsichtigt, jetzt wollen wir die Formularwerte auswerten".

Betrachten Sie dieses Beispiel einer wirklich einfachen SignInForm, die in React geschrieben wurde:

import React from 'react';

class SignInForm extends React.Component {
  constructor() {
    this.state = {
      email: '',
      password: '',
    };

    this.handleEmail = this.handleEmail.bind(this);
    this.handlePassword = this.handlePassword.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleEmail(event) {
    this.setState({ email: event.target.value });
  }

  handlePassword(event) {
    this.setState({ password: event.target.value });
  }

  handleSubmit() {
   console.log(this.state.email); // The email value
   console.log(this.state.password); // The password value
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
         <input
            name="email"
            type="text"
            value={this.state.email}
            onChange={this.handleEmail}
            placeholder="Email"
          />
         <input
            name="password"
            type="text"
            value={this.state.password}
            onChange={this.handlePassword}
            placeholder="Password"
          />
          <button type="submit" onClick={this.handleSubmit}>Sign In</button>
        </form>
    );
  }
}

export default SignInForm;

Nach dem Absenden aktualisiert und bewertet das Formular die Eingabefelder entsprechend.

Das heisst:

  1. Wir können die Schaltfläche "Senden" überhaupt nicht deaktivieren
  2. Die gesamte Validierung muss erfolgen, sobald der Benutzer auf diese Schaltfläche klickt

Meiner Meinung nach ist dies der pragmatischste Ansatz und erspart viel Kopfschmerzen. Ich hoffe, das hilft anderen in Zukunft.

Bearbeiten: Für diejenigen, die mit React nicht vertraut sind, können Sie unter diesem Link eine grundlegende Implementierung eines Formulars und einige zusätzliche wichtige Informationen finden: https://html.spec.whatwg.org/multipage/forms.html

Vielen Dank für die Zusammenfassung, aber ich bin gründlich verwirrt. Sie sagen, wenn wir ein Formular senden, wird es "entsprechend aktualisiert". Bedeutet dies, dass zusätzliche Änderungsereignisse für jedes Feld ausgelöst werden, das automatisch ausgefüllt wird, bevor das Übermittlungsereignis ausgelöst wird? Oder bedeutet dies, dass die Werte beim Auslösen des Submit-Ereignisses jetzt über Refs lesbar sind? Wenn es das erstere ist, können wir Komponenten erstellen, wie Sie sie im Snippet gezeigt haben. Wenn es das letztere ist, müssen wir einen ref-basierten Ansatz für Formulare verfolgen, die sich weiterentwickeln.

@thomasjulianstoelen Was hast du gemeint?

@ Woodwardgb
Nach meiner Erfahrung (zumindest mit Chrome) wurden die Felder bei der ersten Interaktion des Benutzers mit der Seite (Klicks, Formularübermittlungen usw.) aktualisiert und Ereignisse mit der Änderung übermittelt, sodass die Modellvariablen aktualisiert werden konnten. Ich habe jedoch noch keine anderen Browser getestet.

Sie können das Attribut autocomplete = "off" (HTML5) setzen oder den Eingabewert im URL-Hash aufzeichnen.

Wir haben uns ein bisschen mehr mit diesem Problem befasst: Chromium hat eine Änderung vorgenommen, um sowohl native "Änderungs-" als auch "Eingabe" -Ereignisse basierend auf diesem Fehlerbericht auszugeben: https://bugs.chromium.org/p/chromium/issues/detail?id= 813175. Aus irgendeinem Grund löst React jedoch immer noch nicht das Ereignis onChange als Reaktion auf eines dieser nativen Ereignisse aus. Dies hängt wahrscheinlich entweder mit der Deduplizierungslogik von React (https://github.com/facebook/react/issues/10135) oder mit der Tatsache zusammen, dass Ereignisse, die von Chrome unter iOS programmgesteuert ausgegeben werden, das Flag isTrusted=false .

Kann jemand aus dem React-Team einen genaueren Blick auf den React onChange -Event-Handler werfen, um herauszufinden, warum das Ereignis nicht ausgelöst wird? @gaearon oder @zpao (zufällige Vermutungen)?

In der Zwischenzeit verwende ich das onInput -Ereignis, das direkt auf das native "Eingabe" -Ereignis wartet.

Ich denke, dies ist das Commit in Chrome, das das Verhalten gebrochen hat:

https://chromium.googlesource.com/chromium/src/+/49bf3cbf7cc6d70643197a604090f8729f9d7404%5E%21/components/autofill/ios/fill/resources/fill.js

Dadurch wird das Flag simulated aus dem Änderungsereignis entfernt, wodurch die Deduplizierungslogik diese Ereignisse wahrscheinlich ignoriert.

@nfiacco , das Commit stammt aus dem Jahr 2018, diese Ausgabe wurde 2014 eröffnet, also auf den ersten summiert ... Es sei denn, die Ursache unterscheidet sich jetzt von der, als die Ausgabe ursprünglich geöffnet wurde?

Ich kam von 2022 zurück

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen