Definitelytyped: اجعل React.SyntheticEvent.target عامًا على T وليس React.SyntheticEvent.currentTarget

تم إنشاؤها على ٢٦ سبتمبر ٢٠١٦  ·  7تعليقات  ·  مصدر: DefinitelyTyped/DefinitelyTyped

حاليًا ، يبدو توقيع Typescript 2.0 لـ React's SyntheticEvent كما يلي:

interface SyntheticEvent<T> {
    currentTarget: EventTarget & T;
    target: EventTarget;
}

وفقًا للالتزام a13fa7abf55daedf25b31258b908548f55962c7a ، كان target في الأصل EventTarget & T ، ولكن تم إرجاع هذا التغيير (على ما يبدو) عن طريق الخطأ أثناء الدمج في الالتزام 5607f54defce88bc52a0440288f434cafffdb5ce.

يكسر التوقيع الحالي الكثير من الكود قبل 2.0 (كما يمكنك أن تتخيل ، كود React مليء بمعالجات الأحداث) للحصول على فائدة قليلة أو معدومة (نظرًا لأن معظم الكود يعتمد على event.target ، لذلك لا يزال هذا يعتمد على ما قبل -2.0 رمز مثل (event.target as any).value ، نظرًا لأن event.target ليس عامًا.

يسعدني تقديم تصحيح ، لكني أود التأكد من أن SyntheticEvent.target لم يتم إلغاء إنشاؤه عن قصد.

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

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

الاعتماد على الهدف بدلاً من CurrentTarget هو خطأ مبتدئ سوف يعضهم في وقت أقرب من الأخير.

على سبيل المثال:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

هذا الرمز يستخدم للترجمة ، كما ينبغي.

مع دمج "الإصلاح" ، لا يمكن الكتابة e.currentTarget (لا يمكنني الوصول إلى مجموعة البيانات الخاصة به بدون خطأ في النوع) ويتم الآن كتابة e.target كـ HTMLLinkElement ، بينما في الواقع لا توجد طريقة يمكننا التأكد من ذلك. (ربما قمت بالنقر فوق الامتداد الداخلي.

نظريًا يمكننا إضافة عام ثانٍ إلى SyntheticEvent ، لكتابة الهدف ، عندما يكون المستخدم متأكدًا منه (لا يوجد أطفال لمعالج الحدث ، أو لديهم جميعًا نفس النوع). لكنها قليلة القيمة ومضللة حقًا (لأنها تنطبق فقط على حالات معينة حيث يكون استخدام الصب أكثر منطقية).
على وجه الخصوص ، إذا لم يكن لديك أطفال ، فيمكنك استخدام currentTarget.

ال 7 كومينتر

ربما يكون هذا خطأ أثناء الدمج. الرجاء إجراء العلاقات العامة.

انظر # 11041 ، # 10784 وغيرها الكثير. هو لغز لماذا لم يتم إصلاحه حتى بعد الدمج.

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

الاعتماد على الهدف بدلاً من CurrentTarget هو خطأ مبتدئ سوف يعضهم في وقت أقرب من الأخير.

على سبيل المثال:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

هذا الرمز يستخدم للترجمة ، كما ينبغي.

مع دمج "الإصلاح" ، لا يمكن الكتابة e.currentTarget (لا يمكنني الوصول إلى مجموعة البيانات الخاصة به بدون خطأ في النوع) ويتم الآن كتابة e.target كـ HTMLLinkElement ، بينما في الواقع لا توجد طريقة يمكننا التأكد من ذلك. (ربما قمت بالنقر فوق الامتداد الداخلي.

نظريًا يمكننا إضافة عام ثانٍ إلى SyntheticEvent ، لكتابة الهدف ، عندما يكون المستخدم متأكدًا منه (لا يوجد أطفال لمعالج الحدث ، أو لديهم جميعًا نفس النوع). لكنها قليلة القيمة ومضللة حقًا (لأنها تنطبق فقط على حالات معينة حيث يكون استخدام الصب أكثر منطقية).
على وجه الخصوص ، إذا لم يكن لديك أطفال ، فيمكنك استخدام currentTarget.

بالإضافة إلى أنه خاطئ تمامًا ، في DOMAttributes<SomeType> ، تحصل على onClick : MouseEventHandler<SomeType> ، ثم تحصل على EventHandler<MouseEvent<SomeType>> مع

    interface EventHandler<E extends SyntheticEvent<any>> {
        (event: E): void;
    }

لا يمكنك مطلقًا كتابة الهدف بشكل مختلف عن CurrentTarget. يتوقع onClick أن يكون معالج الأحداث الذي يتعامل مع الحدث (المعروف أيضًا باسم currentTarget) هو الحدث العام. لا يمكن أن يكون شيئًا آخر ، ولن يتم تجميعه.

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

handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => { ... }

أقترح بدلاً من ذلك:

handleTabClick = (e: React.FormEvent<HTMLLinkElement>) => { ... }

لديك أيضًا ClipboardEvent<T> ، CompositionEvent<T> ، DragEvent<T> ، FocusEvent<T> ، KeyboardEvent<T> ...
SyntheticEvent هو الشيء ذو المستوى المنخفض.

هذا لا يزال هكذا في مستودع

تم تغيير هذا مرة أخرى. انظر # 12239.

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