React: وفر طريقة للتعامل مع قيم النموذج التي يتم إكمالها تلقائيًا في المستعرض على المكونات الخاضعة للرقابة

تم إنشاؤها على ٢٢ فبراير ٢٠١٤  ·  80تعليقات  ·  مصدر: facebook/react

عندما يكون هناك مكون خاضع للتحكم لأسماء النماذج قام المستخدم بحفظه في متصفحه (شائع مع حقول اسم المستخدم / كلمة المرور) ، سيعرض المتصفح أحيانًا الصفحة بقيم في تلك الحقول دون تنشيط أحداث onChange. إذا أرسل المستخدم النموذج ، فإن حالة المكون لا تعكس ما يظهر للمستخدم.

في تجربة هذا ، يبدو أن البيانات موجودة عند التحميل (تم اختبارها عن طريق تسجيل this.refs.myinput.getDOMNode (). value)

DOM Bug

التعليق الأكثر فائدة

هل حاولت تحديد سمة "الاسم" للإدخال؟ يعمل بالنسبة لي. يتم تشغيل onChange عند الملء التلقائي للمستخدم

ال 80 كومينتر

يبدو أن هذا يناقشها أكثر قليلاً: http://stackoverflow.com/a/11710295

أنا أستخدم هذا https://github.com/tbosch/autofill-event

نسخة لي

(نصيحة visionscaper : اضغط على "اشتراك" في العمود الأيمن.)

أي تحديثات أو أفضل الممارسات المقترحة على هذا؟ يبدو أن حدث الملء التلقائي للحشو يشبه حل المطرقة.

يقوم Safari (8) بإرسال أحداث التغيير على الملء التلقائي ، لكنها لا تظهر في شكل فقاعة حتى لا تصل إلى معالج التفاعل.

تم إغلاق مناقشة ذات صلة على https://github.com/angular/angular.js/issues/1460 ، مع بعض الاقتراحات ، أحدها يستخدم https://github.com/tbosch/autofill-event لإطلاق النار حدث التغيير عند الملء التلقائي يدويًا.

أعتقد أنه يمكننا الإغلاق هنا أيضًا.

سيكون من الجيد أن يكون حدث الملء التلقائي كجزء من React ، ممكنًا كملحق. ستكون هذه الوظيفة ضرورية لكل شخص تقريبًا يستخدم React للتحقق من صحة النموذج. يضيف البرنامج النصي لحدث الملء التلقائي أيضًا تبعية لـ jQuery ، والتي قد تكون غير مرغوب فيها في كثير من الحالات.

هذا خطأ في المتصفح يؤثر على جميع المتصفحات بشكل مختلف قليلاً. أعتقد أنه لمجرد أن الزاوي يحاول العمل أو إصلاحه لا يعني أن رد الفعل يجب أن يفعل. إنه أمر شائع لكنني أفهم ما إذا كان هذا "wontfix".

لست على دراية جيدة بمتعقبات الأخطاء في المتصفح المختلفة ، ولكن سيكون من الرائع أن يجد شخص ما أو يفتح مشكلات لهذا الغرض. أعتقد أن فريق رد الفعل له وزن أكبر مما يفعله معظم المستخدمين عند فتح مشكلة حوله. ويمكننا تتبع التذاكر هنا لمطوري التفاعل المهتمين.

لقد ألحقت الخيط الزاوي. يواجه Firefox مشكلات في حقول كلمة المرور (https://bugzilla.mozilla.org/show_bug.cgi؟id=950510 لا يزال مفتوحًا) ، ولا توجد أية معلومات عن خطأ Safari # ، تم إصلاح الكروم.

يتم بالفعل تتبع المشكلات في بعض الأماكن - https://github.com/angular/angular.js/issues/1460#issuecomment -53947546

تم إغلاق مشكلة Chrome الآن ، ولكن من الواضح أنها لا تعمل في Chrome 50 مع React 0.14.8.

لا إصلاح حتى الآن؟

أشعر أن هذا كان يعمل لفترة من الوقت وانكسر مرة أخرى مؤخرًا؟

أي تعديل حدث في هذه القضية؟

إليك مقتطف من الحل الخاص بي لهذه المشكلة:

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

ملاحظة: يأتي value من الولاية و onFieldChange بتحديث الحالة بالقيمة الجديدة

رمز setInterval مأخوذ من https://github.com/Pephers/react-autofill

هل يمكن لأي شخص تأكيد أن هذه المشكلة قد تم إصلاحها مع iOS 10.2؟ لا يمكنني إعادة إنتاجه الآن ...

ما زلت أواجه مشكلات في نظام التشغيل iOS 10.2 مع إصدار Chrome 55.0.2883.79 ... على عكس ما تم وصفه أعلاه ، بالنسبة لي ، يومض المحتوى المعبأ تلقائيًا لفترة وجيزة في النموذج ثم تتم إزالته مرة أخرى.
لذا فهو يتوافق الآن مع ما يتم تخزينه في الحالة ، ومع ذلك ، لا يزال الملء التلقائي لا يعمل ...

أنا أعيد إنتاج نفس المشكلة التي واجهتهاirisSchaffer. لدي تطبيق متماثل ، حيث أقوم بعرض صفحة ثابتة مع رد فعل وصريح ، ثم على العميل أقوم بتصدير الدعائم واستخدم نفس مكون الصفحة.

حتى عند عدم التعامل مع قيمة إدخال كلمة المرور من خلال رد الفعل ، يحذف مكون تفاعل العميل كلمة المرور المحفوظة من الإدخال ، حتى عندما يعرضها الكروم لفترة وجيزة. عندما أقوم بتعطيل جافا سكريبت من المتصفح ، تظل كلمة المرور المحفوظة في مكانها.

هذه المشكلة مرئية على Chrome فقط ، باستخدام إصدارها الأخير ، 58.

لا تتعلق بالتفاعل ، لا يمكن الوصول إلى كلمة المرور المحفوظة من خلال element.value حتى يكون هناك حدث يتم إطلاقه على dom ، مثل التركيز ، أو أي حدث رئيسي ، وما إلى ذلك. حاولت محاكاة إطلاق حدث من خلال جافا سكريبت ، دون حظ في ملء القيمة خاصية.

+1. أي إصلاح أو اختراق؟

ما زلت أواجه هذه المشكلة على iOS 10.3.3 Chrome 60.0.3112.89.

يعمل الملء التلقائي ويملأ الحقل ولكنه لا يغير الحالة.

حل محل الديكور: https://github.com/Pephers/react-autofill

حل بديل للمكون العام:

/**
  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 لنظام iOS (تأكد من الاختبار باستخدام الملء التلقائي من Chrome ، وليس الاقتراحات من لوحة مفاتيح iOS) يصدر فقط change عند الملء التلقائي للقيم. من ناحية أخرى ، ينبعث Mobile Safari من focus ، keydown ، input ، keyup ، change و blur ، مثل هل Chrome و Safari على Mac.

لا تستخدم React الحدث change للحدث العادي <input /> والذي يبدو أنه السبب الأساسي لهذه المشكلة: https://github.com/facebook/react/blob/e932ad68bed656eed5295b61ba74e5d0857902ed/src/renderers /dom/shared/eventPlugins/ChangeEventPlugin.js#L66 -L71

ألن يكون من الممكن تشغيل React onChange أيضًا على أحداث DOM change ؟ هل سيكون هناك أي ضرر في ذلك؟

المشكلة ذات الصلة لنظام التشغيل Chrome iOS: https://bugs.chromium.org/p/chromium/issues/detail ؟id=705275

لقد اختبرت الملء التلقائي والأحداث من خلال الصفحة الصغيرة التالية:

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

يتم إصدار حدث التغيير في Chrome v62 عند التفاف المدخلات بواسطة عنصر <form /> .

هناك معالج حدث onInput الذي سيحصل على قيمة حقل الإدخال إذا تغير.

ما زلت أرى بعض السلوك غير المعتاد هنا مع الملء التلقائي على iOS. يبدو أن مصمم الملء التلقائي للتفاعل أعلاه يعمل بشكل جيد مع الملء التلقائي البسيط ولكن ليس مع اختصارات الملء التلقائي التي توفرها لوحة المفاتيح.

يجب إصلاح ذلك في Chrome لنظام iOS الآن: https://chromium.googlesource.com/chromium/src/+/55518e17850cac0bdc6fca7b24092bea479e34db. لست متأكدًا من موعد تضمين هذا التصحيح في نسخة تم إصدارها.

لماذا يجب استخدام onChange؟
لماذا يتعين علينا استخدام "عند التغيير" وليس "حدث التغيير"

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

يتم إصدار حدث التغيير في Chrome v62 عند التفاف المدخلات بواسطة عنصر <form /> .

أؤكد أن هذا الحل يعمل مع Chrome لملء أرقام الهواتف تلقائيًا عبر autoComplete="tel"
https://github.com/catamphetamine/react-phone-number-input/issues/101

الحلول المذكورة أعلاه باستخدام this._previousValue !== this.input.value للأسف تعمل فقط مع iOS Safari. iOS Chrome .value لا يزال فارغًا بعد الملء التلقائي.

ليس لدي أي فكرة عن كيفية تعامل الأشخاص مع الملء التلقائي في النماذج عند استخدام المكونات الخاضعة للرقابة. ضع في اعتبارك سيناريو تسجيل الدخول هذا:

  • الملء التلقائي للبريد الإلكتروني: لم يتغير شيء ، حتى مع اختراق الحدث ، سيقوم Chrome بالإبلاغ عن البريد الإلكتروني .value أنه فارغ
  • ابدأ في كتابة القيمة في حقل كلمة المرور: يُفقد البريد الإلكتروني لأن حالة React تعتقد أنها فارغة

ما لم تكن هناك طريقة لجعل Chrome يبلغ عن القيمة التي لا يمكنني التفكير فيها في حل بخلاف استخدام المكونات غير الخاضعة للرقابة ، والتحقق من صحة إدخال html5 ، والحصول على قيم النموذج عند الإرسال مثل الأيام الخوالي.

يمكنك تتبع المشكلة (وتمييزها بنجمة) هنا: https://bugs.chromium.org/p/chromium/issues/detail؟id=813175

لم أستطع الحصول على الحل أعلاه للعمل إماDominicTobias. هناك طبقات متعددة من المشاكل. الأول هو أن this.input.value يعود دائمًا فارغًا. ومع ذلك ، اكتشفت أنه إذا استخدمت document.getElementById في كل حلقة ، ثم document.getElementById(id).value - ستسترد القيمة.

هذا لا يحل مشكلة dispatchEvent ، ولكن على الأقل يمكنك الحصول على القيمة المعبأة تلقائيًا ويمكنك فعل أشياء بها (على سبيل المثال ، مجرد استدعاء معالج المدخلات المتحكم فيه onChange ).

من الجيد معرفة

wlingke عند إعداد عرض توضيحي onChange حدث اصطناعي في React لا يستخدم في الواقع حدث change ، والذي يبدو غريبًا جدًا بالنسبة لي.

يمكنك حتى أن ترى في العرض التوضيحي أدناه أنه يتصرف بشكل مختلف ، وكأنه يستمع لحدث input . عند استخدام حدث change الحقيقي ، فإنه يعمل بشكل صحيح في iOS Chrome.

لذا أود أن أقترح الحصول على مرجع للعنصر والاستماع فقط إلى حدث التغيير الحقيقي ، بالإضافة إلى حدث onChange الذي يبدو أنه حدث input إذا كنت بحاجة إلى تحديث الحالة باسم المستخدم يكتب.

العرض التوضيحي: https://kind-stallman-f3c045.netlify.com/

DominicTobias لقد جربت سابقًا كلا change و input بشكل منفصل بالإضافة إلى كلا الحدثين مرة واحدة في هذا المصمم ولكن لم أتمكن من تشغيله في تطبيقي.

كما أنني لست متأكدًا مما إذا كان هذا يغير الأشياء .. ولكن هناك فرق عند الملء التلقائي لحقل واحد مقابل الملء التلقائي لحقول متعددة. حدث input يعمل بشكل جيد عند الملء التلقائي لحقل واحد. ومع ذلك ، في Chrome للجوال ، يمكنك بالفعل ملء مجموعة من الحقول تلقائيًا مرة واحدة من لوحة المفاتيح (مثل الاسم الأول والاسم الأخير والبريد الإلكتروني كل ذلك بنقرة واحدة).

في هذا السيناريو الثاني ، يسمح المصمم للحقل الأول بالتعبئة التلقائية بشكل صحيح (الحقل الأول يعني الحقل الذي يتم التركيز عليه حاليًا). ومع ذلك ، لا يبدو أن المصمم (المرفق بجميع الحقول الثلاثة) يعمل في المجالات الأخرى.

wlingke مثير للاهتمام ، لقد أضفت بعض الحقول الإضافية ولكن عند الملء التلقائي لجميع الحقول الثلاثة مرة واحدة في iOS Chrome ، أتلقى أحداث التغيير بشكل صحيح (ولكن 0 لإصدار React أدناه):

screen shot 2018-03-08 at 19 29 15

(لقطة الشاشة من متصفح سطح المكتب ولكني أحصل على نفس النتيجة على هاتفي)

DominicTobias أعتقد أنه إذا كنت تستخدم الحدث input - وهو ما استخدمته سابقًا ، فسيعمل بشكل كامل على سطح المكتب. و العمل من أجل الإدخال الأول في الجوال.

input هو الأقرب للتفاعل onChange . ملفات الحدث change فقط بعد أن يفقد عنصر التركيز مما أفهمه (https://stackoverflow.com/questions/17047497/what-is-the-difference-between-change-and-input-event- لعنصر المدخلات)

رد فعل Yep مرتبط لسبب ما بالتغيير إلى input event: https://stackoverflow.com/questions/38256332/in-react-whats-the-difference-between-onchange-and-oninput

لذا لتبسيط الأمور ، أسميها أيضًا في مكون Input لأحداث التغيير الفعلي (بالإضافة إلى الإدخال العادي). يعمل الآن في iOS Chrome. جربه واسمحوا لي أن أعرف!

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

تحرير: من المفترض أن يكون Chrome قد تم إصلاحه في الإصدار 65 ولكن الناس أبلغوا أنه لا يزال لا يعمل: /

شكرا لك على الشرح دومينيك. لقد أصلحنا هذا السلوك مرة أخرى في ديسمبر. نحن الآن نطلق أحداث keydown والتغيير والإدخال والمفاتيح الرئيسية.
https://chromium-review.googlesource.com/c/chromium/src/+/771674

لدينا أيضًا إصلاح لـ React.
https://chromium-review.googlesource.com/c/chromium/src/+/844324

بينما يعمل هذا على إصلاح سلوك الملء التلقائي ، فإنه لا يزال لا يستدعي معالج onChange.

لقد أثرت أيضًا مشكلة في هذا الشأن وكان المطور متأكدًا من أنه سيتم إصلاحه في 65 ... https://bugs.chromium.org/p/chromium/issues/detail ؟

أستمع أيضًا إلى الحدث الأصلي change مثل DominicTobias وهو يعمل بالنسبة لي في iOS Chrome. أقوم بتشغيل onChange الخاص بنموذج redux في مستمع الحدث الأصلي المرفق على التحميل.

أنا أستخدم أيضًا المحدد input:-webkit-autofill للتصميم.

شاهد النتيجة بنفسك في الجزء السفلي من https://labrewlangerie.com (نموذج الاتصال).

يبدو أن هذا الإصلاح في طريقه أخيرًا إلى Chrome iOS! لست متأكدًا من الإصدار ، حيث يبدو أنه قد تم دمجه في 1 ديسمبر.

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

نفس الشيء هنا في Chrome 65 ، React 15.6.

قال المحمادي إن هذا عار كان سيبدأ يوم 13 مارس في آية 65:

التعليق 15 بواسطة [email protected] ، 9 مارس
الإصلاح ليس في Chrome 64. بلدي سيئ. يجب أن يكون Chrome 65 (سيتم طرحه بدءًا من 13 مارس). لقد اختبرت للتو موقع الويب التجريبي للأحداث الخاص بك وهو يعمل على Chrome 65. وأنا أقدر لك متابعتك لهذا.

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

حاول الذهاب إلى هنا على هاتفك وتحقق من: https://kind-stallman-f3c045.netlify.com/native.html

الغريب حقًا هو أنه في الإصدار 65 يعمل بشكل أصلي ، ولكن على الرغم من أنه يتم الحصول على مدخلات حتى لم يتم تلقيها في React! بحاجة إلى مزيد من الاستقصاء ، لست متأكدًا تمامًا من كيفية رد الفعل على إرفاق المعالج (أو إذا كان يفعل ذلك على عنصر المستند مثل معالج النقر على سبيل المثال).

أصلاً يمكنني رؤية حدث الإدخال يحدث الآن (https://kind-stallman-f3c045.netlify.com/native.html):

native

لكن بطريقة ما لا تتلقى React أيًا من هذه الأحداث (https://kind-stallman-f3c045.netlify.com):

react

إضافة onBlur = {this.handleChange} على الإدخال

فريق KlarnaUI لديه اختراق مثير للاهتمام للتعامل مع هذه المشكلة باستغلال الحدث onAnimationStart و :-webkit-autofill الفئة الزائفة كما هو موضح في هذه المقالة - https://medium.com/@brunn/detecting -autofilled- الحقول في جافا سكريبت درهم 598d25da7

لقد استخدمنا هذا الاختراق في تطبيقاتنا وهو يعمل بشكل جيد (يمكن اختباره فقط على Chrome). سأحاول ابتكار رقاقة باستخدام هذه التقنية بحيث تكون عامة.

أي تعديل حدث في القضية؟

فوق ، ما هي أفضل خدعة في الوقت الحالي؟

تضمين التغريدة

يبدو أن هذه المشكلة لا تزال قائمة ، أي تحديثات؟

PixelatexAarbel أرى الإجابة قليلا للأعلى - https://github.com/facebook/react/issues/1159#issuecomment -371604044

تستمع React بشكل أساسي إلى حدث input وليس حدث change في onChange ، لذا فإن الإجابة تستمع إلى كليهما.

DominicTobias لقد جربت هذا ولكننا بحاجة إلى نقرة فعلية في مكان ما في الصفحة لإنجاح هذا الأمر. الحدث لا يسجل حتى ذلك الحين.

لقد كنت تكافح بشأن هذه القضية لمدة يوم تقريبًا في المجموع الآن. يمكنني بالتأكيد سرد ما لا يعمل في Desktop Chrome 67 و React 15.6.0:

  1. onAnimationStart مع input:-webkit-autofill https://medium.com/@brunn/detecting -autofilled -field-in-javascript-aed598d25da7 - الحرائق قبل الأوان (لم يتم ملء النموذج بعد)
  2. this.inputRef.addEventListener("transitionend", this.doSomething, false) بالاشتراك مع انتقال css input:-webkit-autofill - يتم إطلاقه في الوقت المحدد ولكن لا يمكنك تنبيه الصفحة ، كما ذكر @ Pixelatex
  3. this.inputRef.addEventListener("change", this.doSomething) - لا يتم إطلاقه حتى تنقر على الصفحة
  4. onBlur={this.doSomething} - لا يطلق أي حدث

مرة أخرى ، هذه الحلول لا تعمل لسوء الحظ. لا يحتوي HTML على القيمة التي تم ملؤها تلقائيًا إلا إذا نقرت الصفحة. الأقرب هو 2 حيث يمكنك كتابة document في وحدة التحكم وستقوم بتنبيه الصفحة ، وحتى الآن لم يعمل هذا برمجيًا.
DominicTobias هل يعمل الحل الخاص بك على Desktop Chrome؟

في الواقع ، لدي اختراق قذر. إذا كنت تستخدم الحل 2 من التعليق السابق ، فيمكنك الاعتماد على [هنا تأتي القذارة] "بيانات النموذج المحفوظة هي بيانات صالحة". ثم يمكنك التقاط الانتقال بعد اكتمال الملء التلقائي للحدث وتمكين زر إرسال ، دعنا نقول. إليك الطريقة:

css:

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

في المنشئ:

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

داخل صنف مكون React الخاص بك:

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

داخل JSX:

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

PS للمكونات الأساسية (مثل input ) ، استخدم ref prop بدلاً من inputRef

في أحدث إصدار من Chrome لسطح المكتب و iOS 12 Safari ، يتسبب التفاف العناصر في <form> الإكمال التلقائي لإرسال حدث onChange.

التفاف rxb في <p> </p> ؟

basarat آسف ، نسيت تخفيض سعر الكود واختفت العلامة ... <form> tag

أي تعديل حدث في هذه القضية؟

أي تعديل حدث في هذه القضية؟

إذا كانت هناك تحديثات ، فستكون متعلقة بهذه المشكلة.

الرجاء عدم النشر إذا لم يكن لديك أي شيء مفيد لإضافته - فأنت ترسل رسائل غير مرغوب فيها إلى كل شخص مشترك في هذه المشكلة. شكر.

لقد أثرت أيضًا مشكلة في هذا الشأن وكان المطور متأكدًا من أنه سيتم إصلاحه في 65 ... https://bugs.chromium.org/p/chromium/issues/detail ؟

للأسف لم يتم تنسيق هذا الإصلاح مع فريق React. لم نكن ندرك أن Chrome على نظام التشغيل iOS يعيّن الآن خاصية حدثت بطريق الخطأ لتشغيل معالج التغيير في الإصدارات السابقة. لم يكن دعم هذا الأمر مقصودًا من جانبنا - وقد أجرينا بالفعل تغييرًا أزال السلوك (لم نكن نعلم أن Chrome بدأ الاعتماد عليه).

إذا كنت تعمل على متصفح وتضيف اختراقًا خاصًا بـ React ، فيرجى التأكد من تكرار الاتصال بشخص ما من فريق React.

يمكن لأي شخص أن يتلخص في هذا الخطأ الحالي . يعالج React كلاً من أحداث المدخلات change و input . إذا أطلق الملء التلقائي أيًا من هؤلاء ، فيجب أن يعمل. لذلك ليس من الواضح ما إذا كانت المشكلة الأصلية هنا لا تزال ذات صلة. أو هناك بعض الأشياء هنا التي قد تكون مشكلات مختلفة

  • يتم تعبئة القيم تلقائيًا قبل "العرض" ، على سبيل المثال ، كانت هناك صفحة SSR تتفاعل وهي ترطيب. أعتقد أننا نستخدم القيمة الصحيحة في هذه الحالة (ccnhunzaker)
  • لا تطلق المدخلات الأحداث عند الملء التلقائي
  • المدخلات تطلق حدثًا مختلفًا ثم تستمع React (يجب حل هذا اعتبارًا من الإصدار 15)

هل فاتني أي شيء هنا ، وهل يعرف أحد المتصفحات التي تعمل أو لا تعمل بشكل صحيح؟

راجع للشغل ، سنرغب في اعتبار هذا جزءًا من # 9657 - من الناحية المثالية ، يجب أن يكون كل ما نفعله هناك جزئيًا في خدمة المساعدة في حل هذه المشكلة.

jquense نستخدم القيمة الصحيحة ، لكننا لا نرسل حدث تغيير:

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

  1. قم بإلغاء تحديد "الترطيب التلقائي"
  2. غيّر القيمة
  3. انقر فوق Hydrate
  4. لا تغيير :(

حسنًا ، لقد أجريت القليل من البحث أيضًا:

أعتقد أن هناك مشكلتين هنا:

  • القيم التي يملأها المتصفح قبل فقدان هيدرات React.
  • لا يطلق Chrome على IOS

هنا موقع ستستخدمه للاختبار: https://jquense.github.io/browser-test-pages/autofill/login/

من خلال ما يمكنني قوله ، تعمل جميع الأنظمة الأساسية والمتصفحات الأخرى بشكل جيد لتحديد القيم المعبأة تلقائيًا

لاحظ أن ما ورد أعلاه عبارة عن صفحة غاتسبي لذا _أيضًا_ يوضح مشكلة SSR

nhunzaker هل لديك أفكار ذكية حول حالة الكروم IOS؟ يبدو أن Vue punted https://github.com/vuejs/vue/issues/7058 أيضًا

لا يؤدي React إلى إيقاف تشغيل الإكمال التلقائي

لقد قدمت خطأً جديدًا في Chrome لمتصفح Chrome في مشكلة iOS: https://bugs.chromium.org/p/chromium/issues/detail؟id=895898

هل حاولت تحديد سمة "الاسم" للإدخال؟ يعمل بالنسبة لي. يتم تشغيل onChange عند الملء التلقائي للمستخدم

eatsjobs نستخدم اسم

اختبرت

$$(':-webkit-autofill')

يعمل على الكروم 70 ، ويعيد المدخلات المعبأة تلقائيًا.

QuantumInformation بالنسبة لي :(

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>

أحاول بهذه الطريقة ، يبدو أن كل شيء يعمل بشكل جيد.
وضع الملء التلقائي حالتي بشكل صحيح. (iOS 12)

بالنسبة لأولئك الذين واجهوا هذه المشكلة مؤخرًا ، فقد سببتها المتصفحات عمدًا لتجنب المخاطر الأمنية.

إذا تمكنا من الوصول إلى القيم المعبأة تلقائيًا بمجرد تحميل الصفحة ، فسيصبح من السهل جدًا كتابة تعليمات برمجية ضارة لاستخراج المعلومات في نموذج مخصص للتصيد الاحتيالي. إعطاء المستخدم أي فرصة للرد. ربما يكون جزءًا من سبب تجاهل المتصفحات autocomplete="off" .

للتغلب على هذه المشكلة نحتاج إلى:

  1. اقبل حقيقة أننا لن (ولن نتمكن أبدًا) من الوصول إلى القيم المعبأة تلقائيًا عند تركيب عقدة DOM
  2. احتضن المخاوف الأمنية التي تثيرها المتصفحات

لحل هذه المشكلة ، فكر مرة أخرى في كيفية تصميم النماذج في الأصل والقصد من استخدامها. عندما ينقر المستخدم على <button type="submit" /> داخل <form> فإنه يقول بشكل أساسي "مرحبًا هذا الإجراء مقصود من قبل المستخدم ، فلنقم الآن بتقييم قيم النموذج".

ضع في اعتبارك هذا المثال من نموذج SignInForm البسيط المكتوب في 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;

عند التقديم ، سيقوم النموذج بتحديث وتقييم حقول المدخلات وفقًا لذلك.

هذا يعنى:

  1. لا يمكننا تعطيل زر الإرسال على الإطلاق
  2. يجب أن تتم جميع عمليات التحقق بمجرد أن ينقر المستخدم على هذا الزر

في رأيي ، هذا هو النهج الأكثر واقعية وسيوفر الكثير من الصداع. آمل أن يساعد هذا الآخرين في المستقبل.

تعديل: بالنسبة لأولئك الذين ليسوا على دراية بـ React ، يمكنك إلقاء نظرة على هذا الرابط للتنفيذ الأساسي لنموذج وبعض المعلومات الإضافية المثيرة: https://html.spec.whatwg.org/multipage/forms.html

بالنسبة لأولئك الذين واجهوا هذه المشكلة مؤخرًا ، فقد سببتها المتصفحات عمدًا لتجنب المخاطر الأمنية.

إذا تمكنا من الوصول إلى القيم المعبأة تلقائيًا بمجرد تحميل الصفحة ، فسيصبح من السهل جدًا كتابة تعليمات برمجية ضارة لاستخراج المعلومات في نموذج مخصص للتصيد الاحتيالي. إعطاء المستخدم أي فرصة للرد. ربما يكون جزءًا من سبب تجاهل المتصفحات autocomplete="off" .

للتغلب على هذه المشكلة نحتاج إلى:

  1. اقبل حقيقة أننا لن (ولن نتمكن أبدًا) من الوصول إلى القيم المعبأة تلقائيًا عند تركيب عقدة DOM
  2. احتضن المخاوف الأمنية التي تثيرها المتصفحات

لحل هذه المشكلة ، فكر مرة أخرى في كيفية تصميم النماذج في الأصل والقصد من استخدامها. عندما ينقر المستخدم على <button type="submit" /> داخل <form> فإنه يقول بشكل أساسي "مرحبًا هذا الإجراء مقصود من قبل المستخدم ، فلنقم الآن بتقييم قيم النموذج".

ضع في اعتبارك هذا المثال من نموذج SignInForm البسيط المكتوب في 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;

عند التقديم ، سيقوم النموذج بتحديث وتقييم حقول المدخلات وفقًا لذلك.

هذا يعنى:

  1. لا يمكننا تعطيل زر الإرسال على الإطلاق
  2. يجب أن تتم جميع عمليات التحقق بمجرد أن ينقر المستخدم على هذا الزر

في رأيي ، هذا هو النهج الأكثر واقعية وسيوفر الكثير من الصداع. آمل أن يساعد هذا الآخرين في المستقبل.

تعديل: بالنسبة لأولئك الذين ليسوا على دراية بـ React ، يمكنك إلقاء نظرة على هذا الرابط للتنفيذ الأساسي لنموذج وبعض المعلومات الإضافية المثيرة: https://html.spec.whatwg.org/multipage/forms.html

شكرًا على الملخص ، لكني مرتبك تمامًا. أنت تقول أنه عند إرسال نموذج ، سيتم "تحديثه وفقًا لذلك". هل هذا يعني أنه سيتم إطلاق أحداث تغيير إضافية لكل حقل يتم ملؤه تلقائيًا قبل إطلاق حدث الإرسال؟ أو هل يعني ذلك أنه عند إطلاق حدث الإرسال ، أصبحت القيم قابلة للقراءة الآن عبر المراجع؟ إذا كان هذا هو الأول ، فيمكننا بناء مكونات مثل التي أظهرتها في المقتطف. إذا كان هذا هو الأخير ، فسنحتاج إلى اعتماد نهج قائم على المرجع للنماذج التي تتحرك إلى الأمام.

thomasjulianstoelen ماذا تقصد؟

تضمين التغريدة
من خلال تجربتي (مع chrome ، على الأقل) ، فقد تم تحديث الحقول في أول تفاعل للمستخدم مع الصفحة (النقرات ، عمليات إرسال النماذج ، إلخ) ، وقد تم إرسال الأحداث مع التغيير ، مما يسمح بتحديث متغيرات النموذج. لم أختبر المتصفحات الأخرى حتى الآن.

يمكنك تعيين سمة الإكمال التلقائي = "إيقاف التشغيل" (HTML5) ، أو تسجيل قيمة الإدخال في تجزئة عنوان url.

التعمق في هذه المشكلة أكثر قليلاً: أجرى Chromium تغييرًا لإصدار كلاً من أحداث "التغيير" و "الإدخال" الأصلية بناءً على تقرير الخطأ هذا: https://bugs.chromium.org/p/chromium/issues/detail؟id= 813175. ومع ذلك ، لسبب ما ، لا تزال React لا تطلق الحدث onChange ردًا على أي من هذين الحدثين الأصليين. من المحتمل أن يكون هذا مرتبطًا بمنطق React الخاص بإلغاء البيانات المكررة (https://github.com/facebook/react/issues/10135) أو حقيقة أن الأحداث المنبعثة برمجيًا بواسطة Chrome على iOS تحمل علامة isTrusted=false .

هل يمكن لشخص من فريق React أن يلقي نظرة أعمق على معالج الحدث React onChange لمعرفة سبب عدم تشغيل الحدث؟ gaearon أو zpao (تخمينات عشوائية)؟

في هذه الأثناء ، أستخدم حدث onInput ، والذي يستمع مباشرةً إلى حدث "input".

أعتقد أن هذا هو الالتزام في Chrome الذي كسر السلوك:

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

إنه يزيل العلامة simulated من حدث التغيير ، والذي ربما يتسبب في تجاهل منطق dedupe لهذه الأحداث.

nfiacco التي تلتزم من 2018 ، تم فتح هذا الإصدار في 2014 ، لذا

لقد عدت من عام 2022

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات