<p>يمكن أن يستدعي رد فعل- dnd مكونًا غير محمّل يتسبب في "خطأ لم يتم تسجيله: تعذر العثور على معرف هدف صالح"</p>

تم إنشاؤها على ٢ يونيو ٢٠١٩  ·  3تعليقات  ·  مصدر: react-dnd/react-dnd

صف الخلل
من الممكن أن يستدعي رد فعل- dnd دالة تجميع تؤدي إلى إلغاء تحميل أحد المكونات ، ثم إجراء استدعاء آخر للتجميع () على المكون غير المركب ، مما يتسبب في حدوث خطأ غير معلوم "تعذر العثور على معرف هدف صالح".

تقوم ميزة Redux في الإرسال () لأحداث السحب والإفلات الخلفية بإنشاء نسخة من جميع المستمعين للأحداث التي تم الاشتراك فيها في البداية ودائمًا ما تتصل بهم بغض النظر عن اشتراكات إعادة الإرسال التي تم إلغاء اشتراكها أثناء إخطار المشتركين (راجع https://stackoverflow.com/questions / 43356080 / redux-unsubscribe-within-componentwillunmount-still-calls-Subscribe-callback). هذا يعني أنه إذا كان هناك شيء مثل حدث السحب html5 الخاص بـ "EndDrag" يؤدي إلى تشغيل إشعار في handleChange () في رد فعل-dnd / src / decorateHandler.tsx: handleChange () ، وتسبب استدعاء التجميع الأول () في إلغاء تحميل أحد المكونات ، قد يتم تشغيل استدعاء collect () للمكون اللاحق في إخطار لاحق لنفس الحدث.

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

اكتشفت هذه المشكلة أثناء محاولتي دمج شجرة قابلة للفرز للتفاعل ، والتي تستخدم رد الفعل-dnd في تطبيقي. يمكنك الاطلاع على مثال للمشكلة وحالة اختبار قابلة لإعادة الاستخدام هنا: https://github.com/frontend-collective/react-sortable-tree/issues/490. تؤدي عملية السحب والإفلات التي يتم إلغاؤها عن طريق تحرير مصدر السحب خارج هدف السحب إلى إعادة إنتاج هذه المشكلة في كل مرة.

يتم لصق الخطأ غير المحقق وتتبع المكدس أدناه ، يوضح تتبع المكدس أن وظيفة الاتصال تستدعي في monitor.canDrop () الذي يفشل على المكونات غير المثبتة.
browser.js: 38 انتهاك ثابت غير معلوم: من المتوقع العثور على هدف صالح.في ثابت (https://xzoq6xprlz.codesandbox.io/node_modules/invariant/browser.js:38:15)في DragDropMonitorImpl.canDropOnTarget (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:67:9)
في DropTargetMonitorImpl.canDrop (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/DropTargetMonitorImpl.js:24:41)
في nodeDropTargetPropInjection (https://xzoq6xprlz.codesandbox.io/node_modules/react-sortable-tree/dist/index.cjs.js:2367:28)
في DragDropContainer.getCurrentState (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:116:29)
في DragDropContainer._this.handleChange (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:45:39)
في handleChange (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:27:21)
في الإرسال (https://xzoq6xprlz.codesandbox.io/node_modules/redux/lib/redux.js:220:7)
في Object.eval [as endDrag] (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropManagerImpl.js:67:21)
في HTML5Backend.handleTopDragEndCapture (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd-html5-backend/lib/cjs/HTML5Backend.js:145:31)
"

الحل

ربما لا يكون الاتصال بالمكونات غير المثبتة هو السلوك الصحيح ، لذلك أضفت عبارة if في رد فعل-dnd / src / decorateHandler.tsx: handleChange يسقط الإشعار إذا كان decorateHandler قد تم إلغاء اشتراكه بالفعل. فرق المرفقة.

diff --git a/packages/react-dnd/src/decorateHandler.tsx b/packages/react-dnd/src/decorateHandler.tsx
index 85385ec..bcd149e 100644
--- a/packages/react-dnd/src/decorateHandler.tsx
+++ b/packages/react-dnd/src/decorateHandler.tsx
@@ -159,6 +159,15 @@ export default function decorateHandler<Props, CollectedProps, ItemIdType>({
                }

                public handleChange = () => {
+                       if (this.disposable.isDisposed) {
+                               console.log("in handleChange")
+                               //because redux takes a snapshot of all subscribers to 
+                               //events when it starts dispatch, it is still possible to call into this even after 
+                               //the subscription has been unsubscribed
+                               //to prevent against calling into unmounted objects, return immediately
+
+                               return
+                       }
                        const nextState = this.getCurrentState()
                        if (!shallowEqual(nextState, this.state)) {
                                this.setState(nextState)
wontfix

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

@ mx2323 هل تم دفع هذا؟ حتى لو كانت شجرة رد الفعل القابلة للفرز لا تزال بحاجة إلى آخر تحديثات رد الفعل ، أعتقد أنها قيد الانتظار

ال 3 كومينتر

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

@ mx2323 هل تم دفع هذا؟ حتى لو كانت شجرة رد الفعل القابلة للفرز لا تزال بحاجة إلى آخر تحديثات رد الفعل ، أعتقد أنها قيد الانتظار

لم ينتهي بي الأمر بدفعها.

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