React: Fournir un moyen de gérer les valeurs de formulaire remplies automatiquement par le navigateur sur les composants contrôlés

Créé le 22 févr. 2014  ·  80Commentaires  ·  Source: facebook/react

Lorsqu'il existe un composant contrôlé pour les noms de formulaire que l'utilisateur a enregistrés dans son navigateur (commun avec les champs de nom d'utilisateur / mot de passe), le navigateur rendra parfois la page avec des valeurs dans ces champs sans déclencher les événements onChange. Si l'utilisateur soumet le formulaire, l'état du composant ne reflète pas ce qui est affiché à l'utilisateur.

En expérimentant cela, il semble que les données sont là au chargement (testé en enregistrant this.refs.myinput.getDOMNode (). Value)

DOM Bug

Commentaire le plus utile

Avez-vous essayé de définir l'attribut «nom» pour l'entrée? ça marche pour moi. le onChange est déclenché lors du remplissage automatique de l'utilisateur

Tous les 80 commentaires

Cela semble en discuter un peu plus: http://stackoverflow.com/a/11710295

cc moi

( Astuce @visionscaper : appuyez sur "S'abonner" dans la colonne de droite.)

Des mises à jour ou des suggestions de bonnes pratiques à ce sujet? L'événement de remplissage automatique polyfill semble être une solution de masse.

Safari (8) envoie les événements de modification lors de la saisie automatique, mais ils ne bouillonnent pas pour ne pas atteindre le gestionnaire de réaction.

Une discussion connexe sur https://github.com/angular/angular.js/issues/1460 a été clôturée, avec quelques suggestions, l'une d'entre elles utilisant https://github.com/tbosch/autofill-event pour tirer modifier l'événement lors du remplissage automatique, manuellement.

Je pense que nous pouvons également clore ici.

Ce serait bien d'avoir l'événement de remplissage automatique dans le cadre de React, possible en tant qu'addon. Cette fonctionnalité sera nécessaire pour pratiquement tout le monde utilisant React pour la validation de formulaire. Le script d'événement de remplissage automatique ajoute également une dépendance pour jQuery, ce qui peut être indésirable dans de nombreux cas.

Il s'agit d'un bogue de navigateur qui affecte tous les navigateurs un peu différemment. Je pense que ce n'est pas parce que angulaire s'est efforcé de contourner le problème ou de le réparer qu'il devrait réagir. C'est une chose courante mais je comprends si c'est un "wontfix".

Je ne connais pas très bien les différents trackers de bogues du navigateur, mais ce serait bien si quelqu'un qui le trouve pouvait trouver ou ouvrir des problèmes pour cela. Je pense que l'équipe de réaction a plus de poids que la plupart des utilisateurs lors de l'ouverture d'un problème à ce sujet. Et nous pourrions trouver ici les billets pour les développeurs de réaction intéressés.

J'ai rattrapé le fil angulaire. Firefox a des problèmes avec les champs de mot de passe (https://bugzilla.mozilla.org/show_bug.cgi?id=950510 est toujours ouvert), aucun mot sur le bogue de safari #, chrome est corrigé

Les problèmes sont déjà suivis à certains endroits - https://github.com/angular/angular.js/issues/1460#issuecomment -53947546

Le problème de Chrome est maintenant clos, mais il ne fonctionne clairement pas dans Chrome 50 avec React 0.14.8.

pas encore de solution?

J'ai l'impression que cela a fonctionné pendant un certain temps et a encore cassé récemment?

une mise à jour sur ce problème?

Voici un extrait de ma solution pour ce problème:

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}
        />
    );
  }
}

REMARQUE: value provient de l'état et onFieldChange met

Le code setInterval provient de https://github.com/Pephers/react-autofill

Quelqu'un peut-il confirmer que ce problème a été résolu avec iOS 10.2? Je ne peux pas le reproduire maintenant ...

J'ai toujours des problèmes sur iOS 10.2 avec la version 55.0.2883.79 de Chrome ... Contrairement à ce qui est décrit ci-dessus cependant, pour moi le contenu rempli automatiquement clignote brièvement dans le formulaire et est ensuite supprimé à nouveau.
Il est donc désormais cohérent avec ce qui est stocké dans l'état, cependant, le remplissage automatique ne fonctionne toujours pas ...

Je reproduis le même problème rencontré par @irisSchaffer. J'ai une application isomorphe, où je rend une page statique avec react et express, puis sur le client j'exporte les accessoires et j'utilise le même composant de page.

Même lorsqu'il ne gère pas la valeur d'entrée du mot de passe via react, le composant client react supprime le mot de passe enregistré de l'entrée, même lorsque chrome l'affiche brièvement. Lorsque je désactive javascript du navigateur, le mot de passe enregistré reste à sa place.

Ce problème est visible sur Chrome uniquement, en utilisant sa dernière version, 58.

Non lié à react, le mot de passe enregistré n'est pas accessible via element.value jusqu'à ce qu'un événement soit déclenché sur le dom, comme le focus, tout événement clé, etc. J'ai essayé de simuler un événement déclenché via javascript, sans succès sur le remplissage de la valeur propriété.

+1. des correctifs ou des hacks?

Je suis toujours confronté à ce problème sur iOS 10.3.3 Chrome 60.0.3112.89.

Le remplissage automatique fonctionne, remplit le champ mais ne change pas l'état.

Solution de contournement du décorateur: https://github.com/Pephers/react-autofill

Solution de contournement générique des composants:

/**
  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 pour iOS (assurez-vous de tester avec le remplissage automatique de Chrome, et non les suggestions du clavier iOS) n'émet que change lors du remplissage automatique des valeurs. Mobile Safari en revanche émet focus , keydown , input , keyup , change et blur , comme fait Chrome et Safari sur Mac.

React n'utilise pas l'événement change pour le <input /> normal, ce qui semble être la cause première de ce problème: https://github.com/facebook/react/blob/e932ad68bed656eed5295b61ba74e5d0857902ed/src/renderers /dom/shared/eventPlugins/ChangeEventPlugin.js#L66 -L71

Ne serait-il pas possible que React onChange se déclenche également sur les événements DOM change ? Y aurait-il du mal à cela?

Problème lié pour Chrome iOS: https://bugs.chromium.org/p/chromium/issues/detail?id=705275

J'ai testé le remplissage automatique et les événements avec la petite page suivante:

<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>

L'événement de modification est émis dans Chrome v62 lorsque vous encapsulez les entrées par un élément <form /> .

theres un gestionnaire d'événements onInput qui récupérera la valeur d'un champ d'entrée s'il change.

Vous voyez toujours un comportement inhabituel ici avec le remplissage automatique sur iOS. Le décorateur de réaction-remplissage automatique ci-dessus semble bien fonctionner avec un remplissage automatique simple, mais pas les raccourcis de remplissage automatique fournis par le clavier.

Cela devrait être corrigé dans Chrome pour iOS maintenant: https://chromium.googlesource.com/chromium/src/+/55518e17850cac0bdc6fca7b24092bea479e34db. Je ne sais pas quand ce patch sera inclus dans une version publiée.

Pourquoi faut-il utiliser onChange?
Pourquoi devons-nous utiliser «onChange» mais pas «événement de changement»

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>
        )
    }
}

L'événement de modification est émis dans Chrome v62 lorsque vous encapsulez les entrées par un élément <form /> .

Je confirme que cette solution fonctionne pour Chrome pour la saisie automatique des numéros de téléphone via autoComplete="tel"
https://github.com/catamphetamine/react-phone-number-input/issues/101

Les solutions ci-dessus utilisant this._previousValue !== this.input.value ne fonctionnent malheureusement que pour iOS Safari. Le .value iOS Chrome est toujours vide après un remplissage automatique.

Je n'ai aucune idée de la manière dont les gens gèrent la saisie automatique dans les formulaires lorsqu'ils utilisent des composants contrôlés. Considérez ce scénario de connexion:

  • e-mail autoFill: rien ne change, même avec le hack dispatchEvent Chrome signalera l'e-mail .value comme vide
  • Commencez à écrire la valeur dans le champ du mot de passe: l'e-mail est perdu car l'état React pense qu'il est vide

À moins qu'il n'y ait un moyen de faire en sorte que Chrome rapporte la valeur, je ne peux pas penser à une solution autre que l'utilisation de composants non contrôlés, la validation des entrées html5 et l'obtention des valeurs de formulaire lors de la soumission comme au bon vieux temps.

Vous pouvez suivre (et marquer) le problème ici: https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Je n'ai pas pu faire fonctionner la solution ci-dessus non plus @DominicTobias. Il y a plusieurs niveaux de problèmes. La première était que this.input.value revenait toujours vide. Cependant, j'ai découvert que si vous utilisez document.getElementById dans chaque boucle, alors document.getElementById(id).value - vous récupérerez une valeur.

Cela ne résout pas le problème dispatchEvent , mais au moins vous pouvez obtenir la valeur remplie automatiquement et faire des choses avec (par exemple, simplement appeler le gestionnaire onChange une entrée contrôlée).

@wlingke bon à savoir (et c'est étrange)! Je devrai aussi emprunter cette voie s'ils ne corrigent pas le bogue à temps pour ma sortie

@wlingke Lors de la configuration d'une démo pour les gars de Chrome, j'ai réalisé quelque chose - ce n'est pas un problème avec Chrome, j'aurais dû lire les commentaires ci-dessus plus attentivement (en particulier @ oscar-b comment). onChange est un événement synthétique dans React qui n'utilise pas réellement l'événement change , ce qui me semble assez étrange.

Vous pouvez même voir dans la démo ci-dessous qu'il se comporte différemment, plus comme s'il écoutait un événement input . Lorsque vous utilisez le vrai événement change , cela fonctionne correctement dans iOS Chrome.

Je suggérerais donc d'obtenir une référence pour l'élément et d'écouter simplement l'événement de changement réel, ainsi que l'événement onChange qui semble être l'événement input si vous devez mettre à jour l'état en tant que l'utilisateur tape.

démo: https://kind-stallman-f3c045.netlify.com/

@DominicTobias J'ai déjà essayé les change et input séparément, ainsi que les deux à la fois dans ce décorateur, mais je n'ai pas pu le faire fonctionner dans mon application.

De plus, je ne suis pas sûr que cela change les choses ... mais il y a une différence entre le remplissage automatique d'un champ et le remplissage automatique de plusieurs champs. L'événement input a bien fonctionné lors du remplissage automatique d'un champ. Cependant, dans Chrome mobile, vous pouvez en fait remplir automatiquement un ensemble de champs à la fois à partir du clavier (comme le prénom, le nom, l'e-mail en un seul clic).

Dans ce deuxième scénario, le décorateur autorise le premier remplissage automatique du premier champ (premier champ signifiant le champ actuellement actif). Cependant, le décorateur (qui est attaché aux 3 champs) ne semble pas fonctionner sur les autres champs.

@wlingke Intéressant, j'ai ajouté quelques champs supplémentaires, mais lors du remplissage automatique des trois à la fois dans iOS Chrome, je reçois correctement les événements de modification de manière native (mais 0 pour la version React ci-dessous):

screen shot 2018-03-08 at 19 29 15

(La capture d'écran provient du navigateur de bureau mais j'obtiens le même résultat sur mon téléphone)

@DominicTobias Je pense que si vous utilisez l'événement input - ce que j'ai précédemment utilisé, cela fonctionnera pleinement dans Desktop. Et travaillez pour la première entrée dans Mobile.

input événement onChange . L'événement change ne file que lorsqu'un élément perd le focus d'après ce que je comprends (https://stackoverflow.com/questions/17047497/what-is-the-difference-between-change-and-input-event- pour un élément d'entrée)

Yep react a pour une raison quelconque lié onChange à l'événement input : https://stackoverflow.com/questions/38256332/in-react-whats-the-difference-b between - oninput

Donc, pour garder les choses simples, je l'appelle simplement dans mon composant Input pour les événements de changement réels (ainsi que ceux d'entrée normaux). Maintenant, cela fonctionne dans iOS Chrome. Essayez-le et faites-le moi savoir!

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);
}

Edit: Chrome est censé avoir été corrigé dans la v65, mais les gens signalent que cela ne fonctionne toujours pas: /

Merci pour l'explication Dominic. Nous avons corrigé ce problème en décembre. Nous déclenchons maintenant les événements keydown, change, input et keyup.
https://chromium-review.googlesource.com/c/chromium/src/+/771674

Nous avons également eu un correctif pour React.
https://chromium-review.googlesource.com/c/chromium/src/+/844324

bien que cela corrige le comportement de remplissage automatique, il n'appelle toujours pas le gestionnaire onChange.

J'ai également soulevé un problème à ce sujet et le développeur était sûr qu'il allait être corrigé dans 65 ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

J'écoute également l'événement natif change comme le fait @DominicTobias et cela fonctionne pour moi dans iOS Chrome. Je déclenche onChange redux-form dans l'écouteur d'événements natif attaché au montage.

J'utilise également le sélecteur input:-webkit-autofill pour le style.

Voyez le résultat par vous-même en bas de https://labrewlangerie.com (formulaire de contact).

On dirait que ce correctif est enfin sur son chemin dans Chrome iOS! Je ne sais pas dans quelle version cependant, car cela semble avoir été fusionné le 1er décembre.

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

Idem ici dans Chrome 65, React 15.6.

C'est dommage, Mahmadi a déclaré qu'il se déroulait le 13 mars sur v65 :(

Commentaire 15 de [email protected] , 9 mars
Le correctif n'est pas dans Chrome 64. Mon problème. Chrome 65 devra (être déployé à partir du 13 mars). Je viens de tester votre site Web de démonstration des événements natifs et il fonctionne sur Chrome 65. Je vous remercie pour le suivi.

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

Essayez d'aller ici sur votre téléphone et vérifiez: https://kind-stallman-f3c045.netlify.com/native.html

Ce qui est vraiment étrange, c'est que dans la v65, cela fonctionne de manière native, mais même s'il reçoit une entrée, même si elle n'est pas reçue dans React! Besoin d'une enquête plus approfondie Je ne sais pas exactement comment réagit l'attachement du gestionnaire (ou s'il le fait sur l'élément de document comme un gestionnaire de clic par exemple).

Nativement, je peux voir l'événement d'entrée se produire maintenant (https://kind-stallman-f3c045.netlify.com/native.html):

native

Mais d'une manière ou d'une autre, React ne reçoit aucun de ces événements (https://kind-stallman-f3c045.netlify.com):

react

add onBlur = {this.handleChange} sur l'entrée

Équipe KlarnaUI a une astuce intéressante pour faire face à ce problème en exploitant le onAnimationStart événement et :-webkit-autofill pseudo - classe comme décrit dans cet article - https://medium.com/@brunn/detecting -autofilled- champs-en-javascript-aed598d25da7

Nous avons utilisé ce hack dans nos applications, il fonctionne bien (ne peut être testé que sur Chrome). Je vais essayer de trouver une cale en utilisant cette technique pour qu'elle soit générique.

Une mise à jour sur le problème?

up, quel est le meilleur truc pour le moment?

@ericflo @sophiebits

Ce problème semble toujours persister, des mises à jour?

@Pixelatex @Aarbel voir ma réponse un peu plus haut - https://github.com/facebook/react/issues/1159#issuecomment -371604044

Fondamentalement, React écoute l'événement input et non le change one pour onChange, donc cette réponse écoute simplement les deux.

@DominicTobias J'ai essayé cela, mais nous devons avoir un clic réel quelque part dans la page pour que cela fonctionne. l'événement ne s'enregistre qu'alors.

J'ai du mal sur la question depuis environ une journée au total maintenant. Je peux certainement énumérer ce qui ne fonctionne PAS dans Desktop Chrome 67 et React 15.6.0:

  1. onAnimationStart avec input:-webkit-autofill https://medium.com/@brunn/detecting -autofilled-fields-in-javascript-aed598d25da7 - se déclenche prématurément (le formulaire n'est pas encore rempli)
  2. this.inputRef.addEventListener("transitionend", this.doSomething, false) en combinaison avec la transition input:-webkit-autofill css - se déclenche à temps mais vous ne pouvez pas réveiller la page, comme @Pixelatex l'a mentionné
  3. this.inputRef.addEventListener("change", this.doSomething) - ne se déclenche même pas tant que vous n'avez pas cliqué sur la page
  4. onBlur={this.doSomething} - ne déclenche pas d'événement

Encore une fois, ces solutions ne fonctionnent pas malheureusement. Le code HTML ne contient pas la valeur remplie automatiquement, sauf si vous piquez la page. Le plus proche est 2 car vous pouvez taper document dans la console et cela réveillera la page, et jusqu'à présent, cela n'a pas fonctionné par programme.
@DominicTobias Votre solution fonctionne-t-elle sur Desktop Chrome?

En fait, j'ai un sale hack. Si vous utilisez la solution 2 du commentaire précédent, vous pouvez compter sur [ici vient la saleté] "Les données de formulaire enregistrées sont des données valides". Ensuite, vous pouvez attraper la transition après l'événement de remplissage automatique terminé et activer un bouton Soumettre, disons. Voici comment:

css:

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

dans le constructeur:

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

Dans votre classe React Component:

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)
}

À l'intérieur de JSX:

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

PS pour les composants de base (comme input ), utilisez ref prop au lieu de inputRef

Dans le dernier bureau Chrome et iOS 12 Safari, l'encapsulation d'éléments dans <form> entraîne l'émission d'un événement onChange par la saisie semi-automatique.

@rxb enveloppant dans <p> </p> ?

@basarat désolé, j'ai oublié mon code markdown et le tag a disparu ... <form> tag

Une mise à jour sur ce problème?

Une mise à jour sur ce problème?

S'il y avait des mises à jour, elles seraient sur ce problème.

Veuillez ne pas publier si vous n'avez rien de significatif à ajouter - vous envoyez du spam à tous ceux qui sont abonnés à ce problème. Merci.

J'ai également soulevé un problème à ce sujet et le développeur était sûr qu'il allait être corrigé dans 65 ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Ce correctif n'a malheureusement pas été coordonné avec l'équipe React. Nous ne savions pas que Chrome sur iOS définit désormais une propriété qui a accidentellement déclenché le gestionnaire de modifications dans les versions précédentes. Ce n'était pas intentionnel de notre part de soutenir cela - et nous avons déjà apporté un changement qui a supprimé le comportement (nous ne savions pas que Chrome avait commencé à s'y fier).

Si vous travaillez sur un navigateur et que vous ajoutez un hack spécifique à React, assurez-vous de faire une boucle dans quelqu'un de l'équipe React.

Quelqu'un peut-il résumer cela au bogue actuel . React gère LES DEUX événements change et input pour les entrées. Si le remplissage automatique déclenche l'un de ces éléments, cela devrait fonctionner. Il n'est donc pas clair que le problème initial ici soit toujours pertinent. OU il y a quelques choses ici qui peuvent être des problèmes différents

  • Les valeurs sont remplies automatiquement avant le «rendu», par exemple il y avait une page SSR qui réagit est hydratante. Je pense que nous utilisons la valeur correcte dans ce cas (cc @nhunzaker)
  • Les entrées ne déclenchent pas d'événements lors du remplissage automatique
  • les entrées déclenchent différents événements alors que React est à l'écoute (cela devrait être résolu à partir de la v15)

Y a-t-il quelque chose que j'ai manqué ici, et est-ce que quelqu'un sait quels navigateurs fonctionnent ou ne se comportent pas correctement?

Btw nous voudrons considérer cela comme une partie de # 9657 - idéalement quoi que nous fassions là-bas devrait être en partie au service d'aider à résoudre ce problème.

@jquense nous utilisons la valeur correcte, mais nous n'envoyons pas d'événement de modification:

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

  1. Décochez "Auto-hydrate"
  2. Changer la valeur
  3. Cliquez sur Hydrate
  4. Pas de changement :(

ok j'ai aussi fait un peu de recherche:

Je pense qu'il y a deux problèmes ici:

  • Valeurs remplies par le navigateur avant la perte des hydrates de React.
  • Chrome sur IOS ne déclenche aucun événement lors du remplissage automatique

voici un site que vous pouvez utiliser pour tester: https://jquense.github.io/browser-test-pages/autofill/login/

D'après ce que je peux dire, toutes les autres plates-formes et navigateurs fonctionnent correctement pour sélectionner des valeurs remplies automatiquement

notez que ce qui précède est une page gatsby donc _aussi_ démontre le problème SSR

@nhunzaker vous avez des idées intelligentes sur le boîtier chromé IOS? ressemble également à Vue punted https://github.com/vuejs/vue/issues/7058

React ne rend pas la saisie semi-automatique désactivée

J'ai déposé un nouveau bogue Chrome pour le problème Chrome sur iOS: https://bugs.chromium.org/p/chromium/issues/detail?id=895898

Avez-vous essayé de définir l'attribut «nom» pour l'entrée? ça marche pour moi. le onChange est déclenché lors du remplissage automatique de l'utilisateur

@eatsjobs Nous utilisons le nom attr, mais nous avons le même problème.

j'ai testé

$$(':-webkit-autofill')

Fonctionne sur chrome 70, renvoie les entrées remplies automatiquement.

@QuantumInformation pareil pour moi :(

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>

J'essaye de cette façon, on dirait que tout fonctionne bien.
La saisie automatique définit correctement mon état. (iOS 12)

Pour ceux qui ont récemment rencontré ce problème, il est causé intentionnellement par les navigateurs pour éviter les risques de sécurité.

Si nous parvenons à accéder aux valeurs remplies automatiquement une fois la page chargée, il deviendrait très facile d'écrire du code malveillant pour extraire des informations sur un formulaire destiné au phishing. Donner à l'utilisateur aucune chance de réagir. Probablement une partie de la raison pour laquelle autocomplete="off" est ignoré par les navigateurs.

Pour surmonter ce problème, nous devons:

  1. Acceptez le fait que nous n'aurons pas (et n'aurons jamais) accès aux valeurs remplies automatiquement lors du montage du nœud DOM
  2. Acceptez les problèmes de sécurité soulevés par les navigateurs

Afin de résoudre ce problème, repensez à la façon dont les formulaires ont été initialement conçus et destinés à être utilisés. Lorsque l'utilisateur clique sur un <button type="submit" /> intérieur d'un <form> il dit essentiellement "hé cette action est voulue par l'utilisateur, évaluons maintenant les valeurs du formulaire".

Considérez cet exemple d'un SignInForm vraiment simple écrit en React:

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;

Lors de la soumission, le formulaire mettra à jour et évaluera les champs d'entrée en conséquence.

Ça signifie:

  1. Nous ne pouvons pas du tout désactiver le bouton d'envoi
  2. Toute la validation doit avoir lieu une fois que l'utilisateur clique sur ce bouton

À mon avis, c'est l'approche la plus pragmatique et vous évitera beaucoup de maux de tête. J'espère que cela aidera les autres à l'avenir.

Edit: Pour ceux qui ne connaissent pas React, vous pouvez consulter ce lien pour une implémentation de base d'un formulaire et quelques informations supplémentaires juteuses: https://html.spec.whatwg.org/multipage/forms.html

Pour ceux qui ont récemment rencontré ce problème, il est causé intentionnellement par les navigateurs pour éviter les risques de sécurité.

Si nous parvenons à accéder aux valeurs remplies automatiquement une fois la page chargée, il deviendrait très facile d'écrire du code malveillant pour extraire des informations sur un formulaire destiné au phishing. Donner à l'utilisateur aucune chance de réagir. Probablement une partie de la raison pour laquelle autocomplete="off" est ignoré par les navigateurs.

Pour surmonter ce problème, nous devons:

  1. Acceptez le fait que nous n'aurons pas (et n'aurons jamais) accès aux valeurs remplies automatiquement lors du montage du nœud DOM
  2. Acceptez les problèmes de sécurité soulevés par les navigateurs

Afin de résoudre ce problème, repensez à la façon dont les formulaires ont été initialement conçus et destinés à être utilisés. Lorsque l'utilisateur clique sur un <button type="submit" /> intérieur d'un <form> il dit essentiellement "hé cette action est voulue par l'utilisateur, évaluons maintenant les valeurs du formulaire".

Considérez cet exemple d'un SignInForm vraiment simple écrit en React:

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;

Lors de la soumission, le formulaire mettra à jour et évaluera les champs d'entrée en conséquence.

Ça signifie:

  1. Nous ne pouvons pas du tout désactiver le bouton d'envoi
  2. Toute la validation doit avoir lieu une fois que l'utilisateur clique sur ce bouton

À mon avis, c'est l'approche la plus pragmatique et vous évitera beaucoup de maux de tête. J'espère que cela aidera les autres à l'avenir.

Edit: Pour ceux qui ne connaissent pas React, vous pouvez consulter ce lien pour une implémentation de base d'un formulaire et quelques informations supplémentaires juteuses: https://html.spec.whatwg.org/multipage/forms.html

Merci pour le résumé, mais je suis complètement confus. Vous dites que lorsque nous soumettons un formulaire, il sera «mis à jour en conséquence». Cela signifie-t-il qu'il déclenchera des événements de modification supplémentaires pour chaque champ rempli automatiquement avant de déclencher l'événement de soumission? Ou cela signifie-t-il que lorsque l'événement de soumission est déclenché, les valeurs sont désormais lisibles via refs? Si c'est le premier, nous pouvons créer des composants comme vous l'avez montré dans l'extrait de code. Si c'est le dernier, nous devrons adopter une approche basée sur la référence pour les formulaires à venir.

@thomasjulianstoelen Que

@dwoodwardgb
D'après mon expérience (avec chrome, au moins), il a mis à jour les champs lors de la première interaction de l'utilisateur avec la page (clics, soumissions de formulaires, etc.) et a soumis des événements avec le changement, permettant aux variables du modèle de se mettre à jour. Cependant, je n'ai pas encore testé d'autres navigateurs.

Vous pouvez définir l'attribut autocomplete = "off" (HTML5) ou enregistrer la valeur d'entrée dans le hachage d'URL.

Creusé un peu plus dans ce problème: Chromium a effectué une modification pour émettre à la fois des événements natifs "modification" et "entrée" en fonction de ce rapport de bogue: https://bugs.chromium.org/p/chromium/issues/detail?id= 813175. Cependant, pour une raison quelconque, React ne déclenche toujours pas l'événement onChange en réponse à l'un ou l'autre de ces événements natifs. Cela est probablement lié à la logique de déduplication de React (https://github.com/facebook/react/issues/10135) ou au fait que les événements émis par programme par Chrome sur iOS portent l'indicateur isTrusted=false .

Un membre de l'équipe React peut-il examiner de plus près le gestionnaire d'événements React onChange pour comprendre pourquoi l'événement n'est pas déclenché? @gaearon ou @zpao (suppositions aléatoires)?

En attendant, j'utilise l'événement onInput , qui écoute directement l'événement natif "input".

Je pense que c'est le commit dans Chrome qui a cassé le comportement:

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

Il supprime l'indicateur simulated de l'événement de modification, ce qui oblige probablement la logique de déduplication à ignorer ces événements.

@nfiacco qui commet date de 2018, ce numéro a été ouvert en 2014, donc à première vue, cela ne s'additionne pas ... À moins que la cause ne soit maintenant différente de celle du problème initial?

Je suis revenu de 2022

Cette page vous a été utile?
0 / 5 - 0 notes