React: Menyediakan cara untuk menangani nilai formulir yang dilengkapi otomatis browser pada komponen yang dikontrol

Dibuat pada 22 Feb 2014  ·  80Komentar  ·  Sumber: facebook/react

Saat ada komponen terkontrol untuk nama formulir yang telah disimpan pengguna di browser mereka (umum dengan kolom nama pengguna / sandi), browser terkadang akan merender halaman dengan nilai di kolom tersebut tanpa mengaktifkan peristiwa onChange. Jika pengguna mengirimkan formulir, status komponen tidak mencerminkan apa yang ditampilkan kepada pengguna.

Saat bereksperimen dengan ini, tampaknya data ada di sana saat dimuat (diuji dengan mencatat nilai this.refs.myinput.getDOMNode ().)

DOM Bug

Komentar yang paling membantu

Sudahkah Anda mencoba menentukan atribut 'nama' untuk masukan? itu berhasil untuk saya. onChange dipicu pada IsiOtomatis pengguna

Semua 80 komentar

Ini sepertinya membahasnya lebih banyak: http://stackoverflow.com/a/11710295

atm saya menggunakan https://github.com/tbosch/autofill-event ini

cc saya

(Kiat @viscaper : tekan "Berlangganan" di kolom kanan.)

Adakah pembaruan atau saran praktik terbaik yang satu ini? Polyfill acara IsiOtomatis sepertinya solusi palu godam.

Safari (8) memang mengirimkan peristiwa perubahan pada pengisian otomatis, tetapi peristiwa tersebut tidak menggelembung sehingga tidak mencapai penangan react.

Diskusi terkait di https://github.com/angular/angular.js/issues/1460 telah ditutup, dengan beberapa saran, salah satunya adalah memanfaatkan https://github.com/tbosch/autofill-event untuk mengaktifkan ubah acara di IsiOtomatis, secara manual.

Saya pikir, kita juga bisa menutup di sini.

Alangkah baiknya jika acara IsiOtomatis sebagai bagian dari React, mungkin sebagai addon. Fungsi ini akan diperlukan untuk hampir semua orang yang menggunakan React untuk validasi formulir. Skrip peristiwa IsiOtomatis juga menambahkan dependensi untuk jQuery, yang mungkin tidak diinginkan dalam banyak kasus.

Ini adalah bug browser yang mempengaruhi semua browser dengan sedikit berbeda. Saya pikir hanya karena sudut punted mencoba untuk bekerja atau memperbaikinya tidak berarti bereaksi harus. Itu hal yang biasa tapi saya mengerti jika ini adalah "wontfix".

Saya tidak terlalu ahli dalam berbagai pelacak bug browser, tetapi alangkah baiknya jika seseorang yang dapat menemukan atau membuka masalah untuk ini. Saya pikir tim react memiliki bobot lebih dari kebanyakan pengguna saat membuka masalah tentang itu. Dan kami dapat mengumpulkan tiket di sini untuk para pengembang yang tertarik.

Saya menyusul dengan benang sudut. Firefox memiliki masalah dengan bidang sandi (https://bugzilla.mozilla.org/show_bug.cgi?id=950510 masih terbuka), tidak ada kabar tentang bug safari #, chrome telah diperbaiki.

Masalah sudah dilacak di beberapa tempat - https://github.com/angular/angular.js/issues/1460#issuecomment -53947546

Masalah Chrome sekarang ditutup, tetapi cukup jelas tidak berfungsi di Chrome 50 dengan React 0.14.8.

belum ada perbaikan?

Saya merasa seperti ini bekerja untuk sementara dan bangkrut lagi baru-baru ini?

ada pembaruan tentang masalah ini?

Berikut ekstrak solusi saya untuk masalah ini:

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

CATATAN: value berasal dari negara bagian dan onFieldChange memperbarui status dengan nilai baru

Kode setInterval berasal dari https://github.com/Pephers/react-autofill

Adakah yang bisa mengonfirmasi bahwa masalah ini telah diperbaiki dengan iOS 10.2? Saya tidak dapat mereproduksinya sekarang ...

Saya masih mengalami masalah di iOS 10.2 dengan Chrome versi 55.0.2883.79 ... Bertentangan dengan apa yang dijelaskan di atas, bagi saya konten yang diisi otomatis berkedip sebentar di formulir dan kemudian dihapus lagi.
Jadi sekarang konsisten dengan apa yang disimpan di negara bagian, namun, IsiOtomatis masih tidak berfungsi ...

Saya mereproduksi masalah yang sama yang dihadapi oleh @irisSchaffer. Saya memiliki aplikasi isomorfik, di mana saya membuat halaman statis dengan react dan express, kemudian pada klien saya mengekspor props dan menggunakan komponen halaman yang sama.

Bahkan saat tidak menangani nilai masukan kata sandi melalui react, komponen react klien menghapus kata sandi yang disimpan dari masukan, bahkan ketika chrome menampilkannya sebentar. Ketika saya menonaktifkan javascript dari browser, kata sandi yang disimpan tetap di tempatnya.

Masalah ini hanya terlihat di Chrome, menggunakan versi terakhirnya, 58.

Tidak berhubungan dengan react, password yang disimpan tidak dapat diakses melalui element.value hingga ada event yang diaktifkan di dom, seperti focus, key event apapun, dll. Mencoba mensimulasikan event fire melalui javascript, namun tidak berhasil mengisi nilai Properti.

+1. ada perbaikan atau peretasan?

Saya masih menghadapi masalah ini di iOS 10.3.3 Chrome 60.0.3112.89.

Pengisian otomatis berfungsi, mengisi bidang tetapi tidak mengubah status.

Mengatasi masalah dekorator: https://github.com/Pephers/react-autofill

Komponen umum mengatasi:

/**
  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 untuk iOS (pastikan Anda mengujinya dengan IsiOtomatis dari Chrome, dan bukan saran dari keyboard iOS) hanya mengeluarkan change saat mengisi otomatis nilai. Mobile Safari di sisi lain mengeluarkan focus , keydown , input , keyup , change dan blur , sebagai melakukan Chrome dan Safari di Mac.

React tidak menggunakan acara change untuk <input /> yang tampaknya menjadi penyebab utama masalah ini: https://github.com/facebook/react/blob/e932ad68bed656eed5295b61ba74e5d0857902ed/src/renderers /dom/shared/eventPlugins/ChangeEventPlugin.js#L66 -L71

Tidakkah mungkin React onChange juga dipicu pada event DOM change ? Akankah ada salahnya?

Masalah terkait untuk Chrome iOS: https://bugs.chromium.org/p/chromium/issues/detail?id=705275

Saya telah menguji autofilling dan event dengan halaman kecil berikut:

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

Peristiwa perubahan dipancarkan di Chrome v62 saat Anda membungkus input dengan elemen <form /> .

ada penangan kejadian onInput yang akan mengambil nilai bidang masukan jika berubah.

Masih melihat beberapa perilaku tidak biasa di sini dengan IsiOtomatis di iOS. Dekorator react-autofill di atas tampaknya bekerja dengan baik dengan autofill sederhana tetapi tidak dengan pintasan autofill yang disediakan oleh keyboard.

Ini harus diperbaiki di Chrome untuk iOS sekarang: https://chromium.googlesource.com/chromium/src/+/55518e17850cac0bdc6fca7b24092bea479e34db. Saya tidak yakin kapan patch ini akan disertakan dalam versi rilis.

Mengapa onChange harus digunakan?
Mengapa kita HARUS menggunakan 'onChange' tapi bukan '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>
        )
    }
}

Peristiwa perubahan dipancarkan di Chrome v62 saat Anda membungkus input dengan elemen <form /> .

Saya mengonfirmasi bahwa solusi ini berfungsi untuk Chrome untuk mengisi otomatis nomor telepon melalui autoComplete="tel"
https://github.com/catamphetamine/react-phone-number-input/issues/101

Solusi di atas menggunakan this._previousValue !== this.input.value sayangnya hanya berfungsi untuk iOS Safari. .value iOS Chrome masih kosong setelah pengisian otomatis.

Saya tidak tahu bagaimana orang menangani IsiOtomatis dalam formulir saat menggunakan komponen yang dikontrol. Pertimbangkan skenario login ini:

  • Isi otomatis email: tidak ada yang berubah, bahkan dengan peretasan dispatchEvent Chrome akan melaporkan email .value sebagai kosong
  • Mulai tulis nilai di bidang kata sandi: email hilang karena status React menganggapnya kosong

Kecuali ada cara agar Chrome melaporkan nilai, saya tidak dapat memikirkan solusi selain menggunakan komponen yang tidak terkontrol, validasi input html5, dan mendapatkan nilai formulir saat dikirimkan seperti dulu.

Anda dapat melacak (dan memberi bintang) masalahnya di sini: https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Saya tidak bisa mendapatkan solusi di atas untuk bekerja dengan @DominicTobias. Ada banyak lapisan masalah. Yang pertama adalah bahwa this.input.value selalu kosong. Namun, saya menemukan, bahwa jika Anda menggunakan document.getElementById di setiap loop, kemudian document.getElementById(id).value - Anda akan mendapatkan nilai kembali.

Ini tidak menyelesaikan masalah dispatchEvent , tetapi setidaknya Anda bisa mendapatkan nilai yang diisi otomatis dan dapat melakukan hal-hal dengannya (misalnya hanya memanggil penangan onChange dari input terkontrol).

@wlingke senang mengetahuinya (dan betapa anehnya)! Saya harus menempuh rute itu juga jika mereka tidak memperbaiki bug tepat waktu untuk rilis saya

@wlingke Saat menyiapkan demo untuk orang-orang Chrome, saya menyadari sesuatu - ini bukan masalah dengan Chrome, saya seharusnya membaca komentar di atas dengan lebih cermat (khususnya komentar @ oscar-b). onChange adalah acara sintetis di React yang sebenarnya tidak menggunakan acara change , yang tampaknya cukup aneh bagi saya.

Anda bahkan dapat melihat dalam demo di bawah ini bahwa perilakunya berbeda, lebih seperti mendengarkan acara input . Saat Anda menggunakan acara change acara tersebut berfungsi dengan baik di iOS Chrome.

Jadi saya akan menyarankan untuk mendapatkan referensi ke elemen dan hanya mendengarkan acara perubahan nyata, serta acara onChange yang tampaknya menjadi acara input jika Anda perlu memperbarui status sebagai pengguna sedang mengetik.

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

@DominicTobias Saya sebelumnya mencoba acara change dan input secara terpisah serta keduanya sekaligus di dekorator itu tetapi tidak dapat membuatnya berfungsi di aplikasi saya.

Saya juga tidak yakin apakah ini mengubah banyak hal .. tetapi ada perbedaan saat mengisi otomatis SATU bidang dibandingkan mengisi otomatis bidang GANDA. Peristiwa input berfungsi dengan baik saat mengisi otomatis satu bidang. Namun, di chrome seluler Anda sebenarnya dapat mengisi otomatis sekumpulan bidang sekaligus dari keyboard (seperti nama depan, nama belakang, email semua dengan satu ketukan).

Dalam skenario kedua tersebut, dekorator memungkinkan kolom pertama mengisi otomatis dengan benar (kolom pertama berarti kolom yang sedang dalam fokus). Namun, dekorator (yang dilampirkan ke semua 3 bidang), tampaknya tidak berfungsi di bidang lain.

@wlingke Menarik, saya menambahkan beberapa bidang lagi tetapi ketika mengisi otomatis ketiganya sekaligus di iOS Chrome, saya benar-benar menerima peristiwa perubahan secara asli (tetapi 0 untuk versi React di bawah):

screen shot 2018-03-08 at 19 29 15

(Tangkapan layar berasal dari browser desktop tetapi saya mendapatkan hasil yang sama di ponsel saya)

@DominicTobias Saya rasa jika Anda menggunakan acara input - yang saya gunakan sebelumnya, ini akan bekerja sepenuhnya di Desktop. Dan bekerja untuk masukan pertama di Seluler.

Acara input paling dekat dengan reaksi onChange . File peristiwa change setelah elemen kehilangan fokus dari apa yang saya pahami (https://stackoverflow.com/questions/17047497/what-is-the-difference-between-change-and-input-event- untuk-elemen-masukan)

Yap bereaksi karena alasan tertentu terikat pada acara input : https://stackoverflow.com/questions/38256332/in-react-whats-the-difference-between-onchange-and-oninput

Jadi untuk menyederhanakannya, saya juga menyebutnya dalam komponen Input untuk peristiwa perubahan aktual (serta peristiwa input normal). Sekarang berfungsi di iOS Chrome. Cobalah dan beri tahu saya!

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

Sunting: Chrome seharusnya telah diperbaiki di v65 tetapi orang-orang melaporkan itu masih tidak berfungsi: /

Terima kasih atas penjelasan Dominic. Kami memperbaiki perilaku itu pada bulan Desember. Kami sekarang mengaktifkan peristiwa keydown, perubahan, masukan, dan keyup.
https://chromium-review.googlesource.com/c/chromium/src/+/771674

Kami juga memperbaiki React.
https://chromium-review.googlesource.com/c/chromium/src/+/844324

sementara ini memperbaiki perilaku IsiOtomatis, ini masih tidak memanggil penangan onChange.

Saya juga mengangkat masalah tentang ini dan pengembang yakin itu akan diperbaiki di 65 ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Saya juga mendengarkan acara asli change seperti yang dilakukan @DominicTobias dan berfungsi untuk saya di iOS Chrome. Saya memicu onChange bentuk redux di pendengar acara asli yang terpasang di mount.

Saya juga menggunakan pemilih input:-webkit-autofill untuk penataan.

Lihat hasilnya sendiri di bagian bawah https://labrewlangerie.com (formulir kontak).

Sepertinya perbaikan ini akhirnya menuju Chrome iOS! Tidak yakin dalam versi apa, karena tampaknya ini telah digabungkan pada 1 Desember.

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

Sama di sini di Chrome 65, React 15.6.

Sayang sekali, Mahmadi bilang itu akan masuk pada 13 Maret di v65 :(

Komentar 15 oleh [email protected] , 9 Maret
Perbaikan tidak ada di Chrome 64. Saya buruk. Chrome 65 harus (diluncurkan mulai 13 Maret). Saya baru saja menguji situs web demo acara asli Anda dan berfungsi di Chrome 65. Saya menghargai Anda menindaklanjuti ini.

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

Coba buka di sini di ponsel Anda dan periksa: https://kind-stallman-f3c045.netlify.com/native.html

Yang benar-benar aneh adalah bahwa di v65 ini berfungsi secara native, tetapi meskipun mendapatkan input bahkan tidak diterima di React! Perlu penyelidikan lebih lanjut Saya tidak begitu yakin bagaimana react melampirkan handler (atau apakah itu melakukannya pada elemen dokumen seperti handler klik misalnya).

Secara asli saya dapat melihat acara input terjadi sekarang (https://kind-stallman-f3c045.netlify.com/native.html):

native

Tetapi entah bagaimana React tidak menerima kejadian-kejadian itu (https://kind-stallman-f3c045.netlify.com):

react

tambahkan onBlur = {this.handleChange} pada masukan

Tim KlarnaUI memiliki peretasan yang menarik untuk menangani masalah ini dengan mengeksploitasi acara onAnimationStart dan kelas pseudo :-webkit-autofill seperti yang dijelaskan dalam artikel ini - https://medium.com/@brunn/detecting -autofilled- field-in-javascript-aed598d25da7

Kami telah menggunakan retasan ini di aplikasi kami, ini berfungsi dengan baik (hanya dapat menguji di Chrome). Saya akan mencoba membuat shim menggunakan teknik ini sehingga menjadi generik.

Ada pembaruan tentang masalah ini?

up, apa trik terbaik untuk saat ini?

@ericflo @sophiebits

Masalah ini sepertinya masih berlanjut, ada pembaruan?

@Pixelatex @Aarbel lihat jawaban saya lebih jauh - https://github.com/facebook/react/issues/1159#issuecomment -371604044

Pada dasarnya React mendengarkan acara input bukan change satu untuk onChange, jadi jawaban itu hanya mendengarkan keduanya.

@DominicTobias Saya mencoba ini tetapi kami harus memiliki klik aktual di suatu tempat di halaman untuk membuat ini berfungsi. acara tidak terdaftar sampai saat itu.

Telah berjuang tentang masalah ini selama sekitar satu hari total sekarang. Saya pasti dapat membuat daftar apa yang TIDAK berfungsi di Desktop Chrome 67 dan React 15.6.0:

  1. onAnimationStart dengan input:-webkit-autofill https://medium.com/@brunn/detecting -autofilled-fields-in-javascript-aed598d25da7 - aktif sebelum waktunya (formulir belum diisi)
  2. this.inputRef.addEventListener("transitionend", this.doSomething, false) dalam kombinasi dengan input:-webkit-autofill css transisi - aktif tepat waktu tetapi Anda tidak dapat membangunkan halaman, seperti yang disebutkan @Pixelatex
  3. this.inputRef.addEventListener("change", this.doSomething) - bahkan tidak menyala sampai Anda mengklik halaman
  4. onBlur={this.doSomething} - tidak mengaktifkan acara

Sekali lagi, sayangnya solusi ini TIDAK BEKERJA. HTML tidak berisi nilai isi otomatis kecuali Anda mencolek halaman. Yang paling dekat adalah 2 karena Anda dapat mengetik document di konsol dan itu akan membangunkan halaman, dan sejauh ini secara terprogram ini tidak berhasil.
@DominicTobias Apakah solusi Anda berfungsi di Chrome Desktop?

Sebenarnya, saya memiliki peretasan yang kotor. Jika Anda menggunakan solusi 2 dari komentar sebelumnya, Anda dapat mengandalkan [di sinilah kekotoran] "Data Formulir Tersimpan adalah Data yang Valid". Kemudian Anda dapat melihat transisi setelah acara pengisian otomatis selesai dan mengaktifkan tombol Kirim, misalnya. Begini caranya:

css:

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

dalam konstruktor:

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

Di dalam kelas Komponen React Anda:

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

Di dalam JSX:

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

PS untuk komponen dasar (seperti input ), gunakan ref prop daripada inputRef

Di desktop Chrome dan Safari iOS 12 terbaru, membungkus elemen dalam <form> memang menyebabkan pelengkapan otomatis mengeluarkan acara onChange.

@rxb membungkus <p> </p> ?

@basarat maaf, lupa penurunan harga kode saya dan tag hilang ... <form> tag

Ada pembaruan tentang masalah ini?

Ada pembaruan tentang masalah ini?

Jika ada pembaruan, mereka akan membahas masalah ini.

Harap jangan memposting jika Anda tidak memiliki sesuatu yang berarti untuk ditambahkan - Anda mengirim spam ke semua orang yang berlangganan masalah ini. Terima kasih.

Saya juga mengangkat masalah tentang ini dan pengembang yakin itu akan diperbaiki di 65 ... https://bugs.chromium.org/p/chromium/issues/detail?id=813175

Perbaikan ini sayangnya tidak dikoordinasikan dengan tim React. Kami tidak menyadari bahwa Chrome di iOS sekarang menyetel properti yang secara tidak sengaja memicu penangan perubahan di versi sebelumnya. Itu tidak disengaja di pihak kami untuk mendukung ini - dan kami telah membuat perubahan yang menghapus perilaku (kami tidak sadar Chrome mulai mengandalkannya).

Jika Anda bekerja di browser dan menambahkan peretasan khusus React, harap pastikan untuk menghubungi seseorang dari tim React.

Adakah yang bisa merebus ini menjadi bug saat ini . React menangani event KEDUA change dan input untuk input. Jika IsiOtomatis mengaktifkan salah satu fitur tersebut, maka fitur itu akan berfungsi. Jadi tidak jelas apakah masalah aslinya di sini masih relevan. ATAU ada beberapa hal di sini yang mungkin menjadi masalah berbeda

  • Nilai diisi otomatis sebelum "render" misalnya ada halaman SSR yang bereaksi menghidrasi. Saya yakin kami menggunakan nilai yang benar dalam kasus itu (cc @nhunzaker)
  • Input tidak mengaktifkan peristiwa pada IsiOtomatis
  • masukan api peristiwa yang berbeda maka React sedang mendengarkan (ini harus diselesaikan pada v15)

Apakah ada sesuatu yang saya lewatkan di sini, dan apakah ada yang tahu browser mana yang berfungsi atau tidak berfungsi dengan benar?

Ngomong-ngomong, kami ingin menganggap ini sebagai bagian dari # 9657 - idealnya apa pun yang kami lakukan di sana harus sebagian digunakan untuk membantu memecahkan masalah ini.

@jquense kami menggunakan nilai yang benar, tetapi kami tidak mengirim acara perubahan:

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

  1. Hapus centang "Auto-hydrate"
  2. Ubah nilainya
  3. Klik Hidrat
  4. Tidak ada perubahan :(

ok, saya juga telah melakukan sedikit riset:

Saya pikir ada dua masalah di sini:

  • Nilai yang diisi oleh browser sebelum React hydrates hilang.
  • Chrome di IOS tidak mengaktifkan peristiwa apa pun di IsiOtomatis

berikut adalah situs yang dapat Anda gunakan untuk menguji: https://jquense.github.io/browser-test-pages/autofill/login/

Dari apa yang saya tahu, semua platform dan browser lain berfungsi dengan baik untuk memilih nilai yang diisi otomatis

perhatikan bahwa di atas adalah halaman gatsby jadi _also_ mendemonstrasikan masalah SSR

@nhunzaker Anda memiliki ide cerdas tentang kasus chrome IOS? sepertinya Vue punted https://github.com/vuejs/vue/issues/7058 juga

React tidak membuat pelengkapan otomatis mati

Saya telah mengajukan bug Chrome baru untuk masalah Chrome di iOS: https://bugs.chromium.org/p/chromium/issues/detail?id=895898

Sudahkah Anda mencoba menentukan atribut 'nama' untuk masukan? itu berhasil untuk saya. onChange dipicu pada IsiOtomatis pengguna

@eatsjobs Kami menggunakan nama attr, tetapi memiliki masalah yang sama.

Saya diuji

$$(':-webkit-autofill')

Bekerja pada chrome 70, mengembalikan input pengisian otomatis.

@QuantumInformation sama untuk saya :(

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>

Saya mencoba cara ini, sepertinya semuanya bekerja dengan baik.
IsiOtomatis menyetel status saya dengan benar. (ios 12)

Bagi mereka yang menemukan masalah ini baru-baru ini, ini disebabkan oleh browser secara sengaja untuk menghindari risiko keamanan.

Jika kami dapat mengakses nilai yang diisi otomatis setelah halaman dimuat, akan menjadi sangat mudah untuk menulis kode berbahaya untuk mengekstrak informasi pada formulir yang ditujukan untuk phishing. Memberi pengguna tidak ada kesempatan untuk bereaksi. Mungkin sebagian dari alasan mengapa autocomplete="off" diabaikan oleh browser.

Untuk mengatasi masalah ini kita perlu:

  1. Terima fakta bahwa kami tidak akan (dan tidak akan pernah) memiliki akses ke nilai yang diisi otomatis saat node DOM dipasang
  2. Rangkul masalah keamanan yang dibawa oleh browser

Untuk mengatasi masalah ini, pikirkan kembali bagaimana formulir awalnya dirancang dan dimaksudkan untuk digunakan. Ketika pengguna mengklik <button type="submit" /> di dalam <form> itu pada dasarnya mengatakan "hei tindakan ini dimaksudkan oleh pengguna, sekarang mari kita evaluasi nilai formulir".

Pertimbangkan contoh SignInForm yang sangat sederhana ini yang ditulis di 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;

Setelah diserahkan, formulir akan memperbarui dan mengevaluasi bidang masukan yang sesuai.

Ini berarti:

  1. Kami tidak dapat menonaktifkan tombol kirim sama sekali
  2. Semua validasi harus terjadi setelah pengguna mengklik tombol ini

Menurut saya, ini adalah pendekatan yang paling pragmatis dan akan menghemat banyak sakit kepala. Saya harap ini membantu orang lain di masa depan.

Sunting: Bagi mereka yang tidak terbiasa dengan React, Anda dapat melihat tautan ini untuk implementasi dasar formulir dan beberapa info menarik tambahan: https://html.spec.whatwg.org/multipage/forms.html

Bagi mereka yang menemukan masalah ini baru-baru ini, ini disebabkan oleh browser secara sengaja untuk menghindari risiko keamanan.

Jika kami dapat mengakses nilai yang diisi otomatis setelah halaman dimuat, akan menjadi sangat mudah untuk menulis kode berbahaya untuk mengekstrak informasi pada formulir yang ditujukan untuk phishing. Memberi pengguna tidak ada kesempatan untuk bereaksi. Mungkin sebagian dari alasan mengapa autocomplete="off" diabaikan oleh browser.

Untuk mengatasi masalah ini kita perlu:

  1. Terima fakta bahwa kami tidak akan (dan tidak akan pernah) memiliki akses ke nilai yang diisi otomatis saat node DOM dipasang
  2. Rangkul masalah keamanan yang dibawa oleh browser

Untuk mengatasi masalah ini, pikirkan kembali bagaimana formulir awalnya dirancang dan dimaksudkan untuk digunakan. Ketika pengguna mengklik <button type="submit" /> di dalam <form> itu pada dasarnya mengatakan "hei tindakan ini dimaksudkan oleh pengguna, sekarang mari kita evaluasi nilai formulir".

Pertimbangkan contoh SignInForm yang sangat sederhana ini yang ditulis di 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;

Setelah diserahkan, formulir akan memperbarui dan mengevaluasi bidang masukan yang sesuai.

Ini berarti:

  1. Kami tidak dapat menonaktifkan tombol kirim sama sekali
  2. Semua validasi harus terjadi setelah pengguna mengklik tombol ini

Menurut saya, ini adalah pendekatan yang paling pragmatis dan akan menghemat banyak sakit kepala. Saya harap ini membantu orang lain di masa depan.

Sunting: Bagi mereka yang tidak terbiasa dengan React, Anda dapat melihat tautan ini untuk implementasi dasar formulir dan beberapa info menarik tambahan: https://html.spec.whatwg.org/multipage/forms.html

Terima kasih atas ringkasannya, namun saya benar-benar bingung. Anda mengatakan bahwa ketika kami mengirimkan formulir, itu akan "diperbarui sesuai". Apakah ini berarti ini akan mengaktifkan peristiwa perubahan tambahan untuk setiap bidang yang diisi secara otomatis sebelum mengaktifkan peristiwa pengiriman? Atau apakah itu berarti bahwa ketika event submit diaktifkan, nilainya sekarang dapat dibaca melalui referensi? Jika yang pertama, kami dapat membuat komponen seperti yang Anda tunjukkan di cuplikan. Jika itu yang terakhir maka kita perlu mengadopsi pendekatan berbasis referensi untuk formulir yang bergerak maju.

@thomasjulianstoelen Apa maksud Anda?

@bayu_joo
Dalam pengalaman saya (dengan chrome, setidaknya), telah memperbarui bidang pada interaksi pertama pengguna dengan halaman (klik, pengiriman formulir, dll), dan telah mengirimkan peristiwa dengan perubahan, memungkinkan variabel model untuk diperbarui. Saya belum menguji browser lain.

Anda dapat menyetel atribut autocomplete = "off" (HTML5), atau mencatat nilai masukan dalam hash url.

Gali lebih dalam masalah ini: Chromium membuat perubahan untuk mengeluarkan peristiwa asli "perubahan" dan "masukan" berdasarkan laporan bug ini: https://bugs.chromium.org/p/chromium/issues/detail?id= 813175. Namun, untuk beberapa alasan, React masih tidak memicu event onChange sebagai respon dari salah satu event native ini. Ini mungkin terkait dengan logika deduplikasi React (https://github.com/facebook/react/issues/10135) atau fakta bahwa peristiwa yang dipancarkan secara terprogram oleh Chrome di iOS membawa bendera isTrusted=false .

Bisakah seseorang dari tim React melihat lebih dalam ke event handler React onChange untuk mencari tahu mengapa event tidak dipicu? @gaearon atau @zpao (tebakan acak)?

Sementara itu, saya menggunakan peristiwa onInput , yang mendengarkan peristiwa "input" asli secara langsung.

Saya pikir ini adalah komit di Chrome yang merusak perilaku:

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

Ini menghapus tanda simulated dari peristiwa perubahan, yang mungkin menyebabkan logika dedupe mengabaikan peristiwa ini.

@nfiacco yang commitnya dari tahun 2018, terbitan ini dibuka tahun 2014, jadi di permukaan itu tidak bertambah ... Kecuali jika penyebabnya sekarang berbeda dengan saat terbitan pertama kali?

Saya kembali dari 2022

Apakah halaman ini membantu?
0 / 5 - 0 peringkat