React-dnd: لا يمكن أن يكون لديك خلفية HTML5 خلفية في نفس الوقت

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

مرحبا دان ،

مجرد واحد سريع - أحاول استخدام المكون الخاص بي الذي يحتوي على react-dnd كتبعية في تطبيق آخر يستخدمه بنفسه_ react-dnd لذا توقع الخطأ أعلاه. في هذه الحالة ، ما هي أفضل طريقة لإصلاح ذلك؟

نظرًا لأن المكون الآخر خاص بي ، يمكنني إزالة المكالمة DragDropContext من أثناء تصدير المكون ولكن بعد ذلك يضحي بإعادة استخدام المكون. ماذا تنصح؟

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

هناك طريقة أخرى أكثر نظافة وهي إنشاء وحدة تولد المصمم لواجهة خلفية معينة ، ثم استخدم المصمم عند الحاجة:

lib / withDragDropContext.js

import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

export default DragDropContext(HTML5Backend);

المكونات / MyComponent.js

import { Component } from 'react';
import withDragDropContext from '../lib/withDnDContext';

class MyComponent extends Component {

  render() {
    return (
     <div>
       // other children
     </div>
   );
}

export default withDragDropContext(MyComponent);

ال 62 كومينتر

تحقق من مصدر DragDropContext . أعتقد أنه يجب أن تكون قادرًا على إعادة استخدام المدير الحالي إذا تم تحديده بواسطة مكون أعلى الشجرة. لكنه لا يزال سؤالا خادعا .. هل لديك أي حلول مقترحة؟

أعتقد أنه يجب أن تكون قادرًا على إعادة استخدام المدير الحالي إذا تم تحديده بواسطة مكون أعلى الشجرة.

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

لسوء الحظ ، الحل الوحيد الذي يمكنني التفكير فيه الآن ، هو تصدير المكون النهائي كما هو ، وتوقع أن يضيف المستخدم DragDropContext مع خلفية من اختيارهم. ما رأيك؟

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

نعم ، هذا ممكن من خلال عدم استخدام DragDropContext تمامًا وبدلاً من ذلك استخدام dragDropManager يدويًا في السياق. قد ينظر المكون الخاص بك في السياق ، ويقوم إما بتمرير dragDropManager أسفل السياق ، أو إنشاء خاص به. على الرغم من أنها تبدو هشة إلى حد ما.

لسوء الحظ ، الحل الوحيد الذي يمكنني التفكير فيه الآن ، هو تصدير المكون النهائي كما هو ، وتوقع أن يقوم المستخدم بإضافة DragDropContext بنهاية خلفية من اختيارهم. ما رأيك؟

أعتقد أن هذا هو الحل الأكثر مرونة. يمكنك أيضًا إبداء الرأي هناك وتصدير <MyComponentContext> الذي يطبق DragDropContext(HTML5Backend) .

تصدير <MyComponentContext> الذي يطبق DragDropContext(HTML5Backend)

أنا آسف ، أنا لا أفهم هذا تمامًا. هل يمكنك توضيح هذا أكثر قليلاً؟

export default function MyTagControlContext(DecoratedClass) {
  return DragDropContext(HTML5Backend)(DecoratedClass);
}

ويمكنك إخبار المستخدمين إما بلف مكون المستوى الأعلى الخاص بهم إلى MyTagControlContext أو استخدام DragDropContext مباشرةً إذا كانوا _ بالفعل يستخدمون React DnD.

آه! وماذا عن هذا؟ هل هذا يبدو قبيح جدا؟

// in main component file
module.exports = {
    WithContext: DragDropContext(HTML5Backend)(ReactTags),
    WithOutContext: ReactTags
};

يمكن أن يكون الاستخدام شيئًا مثل

var ReactTags = require('react-tags').WithContext; // if your app doesn't use react-dnd
var ReactTags = require('react-tags').WithOutContext; // if your app already uses react-dnd.

لا أعتقد أن هذا سينجح لأن كل <ReactTags> سيحصل على نسخته الخاصة من الخلفية ويؤدي إلى الخطأ الثابت الذي لصقته أعلاه لأن تلك الخلفيات الخلفية تتعامل مع أحداث النافذة العامة نفسها.

ما أعتقد أنه سينجح هو أنه يمكنك يدويًا إنشاء dragDropManager (تمامًا كما يفعل DragDropContext داخليًا) واستخدام نفس مثيله لجميع حالات ReactTag — مع الرجوع إلى المدير المحدد في context .

أعني تصدير شيء كهذا من مكتبتك:

let defaultManager;
function getDefaultManager() {
    if (!defaultManager) {
        defaultManager = new DragDropManager(HTML5Backend);
    }
    return defaultManager;
}

class ReactTagContext {
    static contextTypes = {
        dragDropManager: PropTypes.object.isRequired
    };

    static childContextTypes = {
        dragDropManager: PropTypes.object.isRequired
    };

    getChildContext() {
        return {
            dragDropManager: this.context.dragDropManager || getDefaultManager()
        };
    }

    render() {
        return <ReactTag {...props} />
    }
}

شكرا جزيلا دان! سأحاول ذلك وأعود إليك. شكرا لتقاسم الكود: ابتسامة عريضة:

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

إذن دان! لأنها من هيك، كنت تحاول الخروج الحل صادرات متعددة فوق -

// in main component file
module.exports = {
    WithContext: DragDropContext(HTML5Backend)(ReactTags),
    WithOutContext: ReactTags
};

في تطبيقي الآخر ، حاولت استيراد المكون دون السياق ، ومن دواعي سروري أنه يبدو أنه يعمل بشكل جيد!

هل تعتقد أن هذا حل مبتكر ويجب أن أمضي قدمًا في ما اقترحته أم يجب أن أترك هذا؟

@ prakhar1989 هل أنت متأكد من أن هذا يعمل مع عدة <Tags /> على الصفحة؟

كنت قد حصلت علي لثانية هناك! : stuck_out_tongue:

img

الحمد لله أنه يعمل!

حسنًا ، ربما يكون الأمر جيدًا ؛-). اسمحوا لي أن أعرف إذا كان لديك أي مشاكل مع هذا النهج!

سوف تفعل! شكرا جزيلا مرة أخرى على كل مساعدتك.

ملاحظة: هل لديك أفكار تسمية أفضل مقابل WithContext و WithoutContext ؟

@ prakhar1989 من المحتمل أن أقوم فقط بتصدير إصدار WithContext مباشرةً ، وأضع NoContext كحقل ثابت عليه.

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

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

سؤالي الأول ، لماذا لا تفعل ذلك ببساطة داخل كود HTML5Backend؟

setup() {
    ...

    // Events already setup - do nothing
    if (this.constuctor.isSetUp) return;

    // Don't throw an error, just return above.
    //invariant(!this.constructor.isSetUp, 'Cannot have two HTML5 backends at the same time.');

    this.constructor.isSetUp = true;
    ...
  }

لماذا لا تفعل ذلك ببساطة داخل كود HTML5Backend

هذه نقطة عظيمة إذا كان المكون قادرًا على اكتشاف العديد من الخلفيات الخلفية ، ألا يمكن أن يكون له منطق الرجوع إلى الواجهة الخلفية الحالية في النطاق؟

مرحبًا gaearon - أواجه هذه المشكلة أيضًا باستثناء حالتي ، لدي صفحة قمت فيها بتجميع مكونات تفاعل متباينة معًا في قالب زاوي بسبب الأداء (الزاوي). ما لدي هو صفحة تبني الأسئلة والخيارات والمزيد في بنية شجرة متكررة. لدي أيضًا شريط أدوات ومكتبة أسئلة تستخدم DnD لإضافة أشياء إلى شجرة الأسئلة. مشكلتي هي أنني قمت الآن بإعداد مكونات تفاعل متعددة تعيش في سياق زاوي. لهذا السبب ، أقوم بلف كل من هؤلاء بـ DragDropContext الذي يسبب هذا الخطأ. حاولت اتباع الموضوع أعلاه ولكن ليس من الواضح تمامًا ما يمكنني فعله لمكونات التفاعل المنفصلة هذه لمشاركة سياق دون تحويل أي شيء آخر على صفحتي إلى React (ليس مثاليًا). أنا معتاد قليلاً على بناء جملة ES6 ولكني أعمل في مشروع لا يزال يستخدم ES5. هل هناك طريقة لتطبيق مفهوم DragDropManager من الأعلى؟ لقد جربته حتى الآن ولا يبدو أنه يمكنني الوصول إلى DragDropManager لأنه في dnd-core

شكرا لمساعدتك وعلى هذه المكتبة الرائعة!

ملاحظة: إذا كان الأمر مهمًا ، فأنا أستخدم ngReact.

@ prakhar1989globexdesignsgaearon

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

أي شخص لديه أي حل سريع لهذا؟ أنا في توقف مسدود في تطوري.

abobwhite هذه هي الطريقة التي قمت بحلها. إنه بالتأكيد ليس حلاً رائعًا ولكن يبدو أنه يعمل حتى الآن.

أتمنى أن يساعدك هذا،

شكرا ، @ prakhar1989 ! لكنني لا أتابع كيف أن التصدير المتعدد مع واحد ملفوف بالسياق والآخر لا يحل المشكلة. لا يتم تضمين مشكلتي في تطبيق آخر باستخدام رد الفعل ولكن بدلاً من ذلك عدم القدرة على التفاف المنطقة التي تم تمكين dnd بها بالكامل (مع العديد من المكونات / التوجيهات المتفاعلة والزاوية) في التفاعل ، لذلك كنت أحاول التفاف السياق حول تلك فقط تفاعل المكونات في صفحتي التي تدعم DnD ... أرغب في تجربة نهج gaearon من الأعلى ولكن لا يمكنني الوصول إلى DragDropManager أجل إنشاء واحد جديد ...

أواجه نفس المشكلة بالضبط. أتفق بشدة مع abobwhite على أن هذا يجعل المكونات أقل قابلية لإعادة الاستخدام.

قادني هذا الموضوع إلى حل مشكلتي الثابتة عن طريق تحريك HTML5Backend و DragDropContext أعلى في التسلسل الهرمي للمكونات ، تمامًا كما يوصي به المستندات .

هذه مشكلة غريبة. أنا أعمل على مكون متداخل قابل لإعادة الترتيب ولدي DragDropContext متداخل داخل المكون الأصلي. يبدو أنه يعمل بشكل مستقل (لكنه لا يزال يحتوي على DragDropContext متداخلة).

ولكن عندما أستخدم هذا المكون داخل مشروع آخر تم فيه تهيئة DragDropContext أعلى التسلسل الهرمي ، أحصل على هذا الخطأ.

واجهت هذه المشكلة مع تطبيق أعمل عليه. كان لدي سيطرة كاملة على جميع المكونات ، لذا انتهى بي الأمر بدلاً من استخدام @DragDropContext(HTMLBackend) انتهى بي الأمر باستخدام شيء قريب جدًا من كود gaearon في هذا التعليق لإنشاء decorator الذي من شأنه أن يعطي سحبًا مشتركًا إسقاط السياق. إنه يعمل بشكل جيد.

لقد حدث لي نفس الشيء للتو وكانت المشكلة أن لدي ComponentA الذي استخدم @DragDropContext(HTMLBackend) ثم ComponentB الذي كان يحتوي أيضًا على @DragDropContext(HTMLBackend) .

تم استيراد ComponentB في ComponentA والذي تسبب لي في الخطأ. كل ما كان علي فعله هو إزالة DragDropContext من ComponentB وعمله.

ماذا لو كان هناك 2 DrapDropContext في التطبيق لكنهما ليسا أحد الوالدين والطفل؟

قضيتي:

  1. تهيئة سياق dnd الأول
  2. استهلال سياق ثاني dnd. 💣

لا يمكنني التحقق من childContext لأن المكون الثاني ليس تابعًا لمكون / سياق dnd الأول

لحل مشكلتي ، قمت بعمل مفرد بهذا الكود:

import { DragDropManager } from 'dnd-core';
import HTML5Backend from 'react-dnd-html5-backend';

let defaultManager;

/**
 * This is singleton used to initialize only once dnd in our app.
 * If you initialized dnd and then try to initialize another dnd
 * context the app will break.
 * Here is more info: https://github.com/gaearon/react-dnd/issues/186
 *
 * The solution is to call Dnd context from this singleton this way
 * all dnd contexts in the app are the same.
 */
export default function getDndContext() {
  if (defaultManager) return defaultManager;

  defaultManager = new DragDropManager(HTML5Backend);

  return defaultManager;
}

ثم في جميع المكونات التي لديها طفل لديه DragDropContext(HTML5Backend) أقوم بإزالته من هؤلاء الطفل وفي والديهم أفعل هذا:

import getDndContext from 'lib/dnd-global-context';

const ParentComponent = React.createClass({

  childContextTypes: {
    dragDropManager: React.PropTypes.object.isRequired,
  },

  getChildContext() {
    return {
      dragDropManager: getDndContext(),
    };
  },

  render() {
    return (<ChildComponentWithDndContext />);
  },

أعتقد أن المفتاح هو أنني أقوم بتهيئة سياق dnd مرة واحدة فقط. ما رأيك؟

تضمين التغريدة إنه يعمل لدي أيضا

andresgutgon أنت الحل رائع ، لكن من الغريب أن DrapDropContext لا يدمر DragDropManager على componentWillUnmount ، أي إذا كنت لا تستخدم 2 DrapDropContext s في نفس الوقت ، ولكن على صفحتين مختلفتين - ما زلت لا تستطيع استخدامها. سأحاول الاختراق في حالتي ، لكن لا يزال من الغريب 100٪ حتى أن يكون لديك اختراق لمثل هذا الموقف التافه.

هل هناك أي فكرة أيضًا عن سبب اعتبار الحصول على 2 DragDropManager أمرًا سيئًا / خاطئًا في react-dnd ؟

هناك طريقة أخرى أكثر نظافة وهي إنشاء وحدة تولد المصمم لواجهة خلفية معينة ، ثم استخدم المصمم عند الحاجة:

lib / withDragDropContext.js

import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

export default DragDropContext(HTML5Backend);

المكونات / MyComponent.js

import { Component } from 'react';
import withDragDropContext from '../lib/withDnDContext';

class MyComponent extends Component {

  render() {
    return (
     <div>
       // other children
     </div>
   );
}

export default withDragDropContext(MyComponent);

مرحبًا ، هل يعرف أي شخص كيفية حل المشكلة عندما يكون لديك مكون واحد ملفوف في DragDropContext ثم مكون آخر يستخدم DragDropContext أيضًا ، ولكن هذا المكون (رد فعل التقويم الكبير) هو حزمة npm ، لذلك إزالته من هناك ليس حل وهم بجوار بعضهما البعض ، وليس أحد الوالدين والطفل ... يمكنك إلقاء نظرة هنا https://github.com/martinnov92/TSCalendar (إنه عمل مستمر - لذا فهو فوضوي قليلاً: D) شكرًا لك

أعتقد أن لدي نفس المشكلة تمامًا في استخدام مدير نوافذ تبليط الفسيفساء المتفاعل والذي يستخدم تفاعل dnd ومكوناتي الخاصة ، والتي تستخدم أيضًا رد الفعل-dnd.

لذلك أعتقد أن هذا لم يتم حله مباشرة في رد الفعل ، ولكن هناك بعض الحلول التي يمكننا تطبيقها.

هل هناك مثال على رمز عمل كامل يعمل على حل هذه المشكلة؟

يعمل حل gcorne

مرحبًا ، لدي نفس المشكلة ولكننا نستخدم شبكة بيانات التفاعل ونحاول إضافة تقويم كبير للتفاعل
بعد إضافة المكون الذي يتضمن رد فعل التقويم الكبير لدينا خطأ "خطأ لم يتم اكتشافه: لا يمكن أن يكون لدينا خلفية HTML5 خلفية في نفس الوقت."

رد فعل كبير التقويم استخدام رد فعل dnd و رد فعل dnd-html5-backend كيفية حل هذه المشكلة؟

مرحبًا szopenkrk ، هل حاولت هذا https://github.com/react-dnd/react-dnd/issues/186#issuecomment -232382782؟
لكنني أعتقد أنك ستحتاج إلى القيام بطلب سحب للرد على التقويم الكبير لقبول خلفية Dnd

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

يبدو الرمز على هذا النحو (TypeScript):

import * as React from 'react';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

// context singleton
let context: Function;

export function withDragDropContext<P>(
    Component: React.ComponentClass<P> | React.StatelessComponent<P>,
): React.ComponentClass<P> {
    // ensure a singleton instance of the context exists
    if (!context) {
        context = DragDropContext<P>(HTML5Backend);
    }

    return context(Component);
}

ثم استخدمه على النحو التالي في مكوناتك:

import * as React from 'react';
import {withDragDropContext} from 'components/WithDragDropContext';

class MyClass extends React.Component<IMyClassProps, {}> {
    // ...
}

export default withDragDropContext<IMyClassProps>(MyClass);

ملحوظة
لم أحاول حتى الآن ولكن من المحتمل أن تكون قادرًا على ملء متغير السياق أثناء الإعلان:

const context = DragDropContext(HTML5Backend);

ثم تخطي الجزء if (!context) {... .

codeaid شكرا لك!

لقد قابلت نفس الموقف مثل andresgutgon ، لكن لم أتمكن من حلها بأسلوبه وكل الطرق التي

لماذا لم يعمل @ guang2013 أي من الحلول هنا؟

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

@ guang2013 إذا كنت تستخدم مكتبة تعتمد على DragDropContext من رد فعل dnd ، فلن تعمل هذه التقنية لأن المكتبة لن تستخدم dndContext الموحد الخاص بك. تسمح لك بعض المكتبات مثل شجرة رد الفعل القابلة للفرز باستخدام المكونات بدون سياق حتى تتمكن من لفها بنفسك.

لقد نجح حل

مشكلة قديمة ، ولكن في حالة وصول شخص آخر هنا من Google:

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

كانت مشكلتي أن DragDropContextProvider كان داخل عنصر BrowserRouter الخاص بـ ReactRouter ، مما جعل HTML5Backend يُعاد بناؤه في كل تنقل ، وإذا كانت كل من الصفحة القديمة (التي تم التنقل فيها بعيدًا) والصفحة الجديدة (التي تم التنقل إليها) تحتوي على عناصر DND ، سيحدث الخطأ أعلاه.

كان الحل هو نقل DragDropContextProvider خارج BrowserRouter.

هذه اللعبة مخصصة لأولئك البشر الذين جربوا ReactDnD لأول مرة ، واتبعوا البرنامج التعليمي وانتهى بهم الأمر بلوحة شطرنج ذات 64 مربعًا.
يمكنني أن أسحب فارسي كما يحلو لي.
كانت المشكلة عندما حاولت إسقاطها في إحدى BoardSquare ، تراجعت مع مشكلة الواجهة الخلفية لـ HTML5.

المأزق

كما ذكر آخرون في التعليقات من قبل ، انقل عرض DragDropContextProvider خارج دورة إعادة عرض التطبيق.
كما هو الحال في ، لا تفعل مباشرة ReactDOM.render كاستدعاء لوظيفة observe .
بدلاً من ذلك ، افعل هذا:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { DragDropContextProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import './index.css';
import App from './App';

ReactDOM.render(
    <DragDropContextProvider backend={HTML5Backend}>
        <App />
    </DragDropContextProvider>,
    document.getElementById('root')
)

App.js

import React, { Component } from 'react';
import Board from './Board';
import { observe } from './Game';

class App extends Component {
    state = {
        knightPosition: [0, 0]
    }

    componentDidMount = () => {
        observe(knightPosition => {
            this.setState(prevState => ({
                ...prevState,
                knightPosition
            }));
        });
    }

    render() {
        return (
            <div className="App">
                <Board knightPosition={this.state.knightPosition} />
            </div>
        );
    }
}

export default App;

أعتقد أن هذا مرتبط بهذه القضية
https://github.com/prakhar1989/react-tags/issues/497

gaearon أعلم أن هذا قديم ، لكن كيف يمكنني الحصول على عقد DragDropManager في مثالك ؟ لا يتم تصديرها في أي مكان.

defaultManager = new DragDropManager(HTML5Backend);

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

تم حل هذه المشكلة عن طريق حذف البنية القديمة.
ما عليك سوى حذف مجلد dist أو تحرير index.html. لا أعرف المشكلة بالضبط ولكن هذا نجح معي

لحسن الحظ ، يمكنني العثور على الإجابة (المخفية) لـ gcorne (https://github.com/react-dnd/react-dnd/issues/186#issuecomment-282789420). لقد حلت مشكلتي - التي كان يُفترض أنها صعبة - على الفور.
@ prakhar1989 لدي شعور بأنها إجابة طرف حقيقية وأنه يجب إبرازها بطريقة ما ، لذا ربما ربطها في وصف الخطأ؟

الحل الذي توصلت إليه والذي يناسبني ويسمح لي باستخدام HTML5 أو Touch backend هو:

قم بإنشاء مكون فردي ذو ترتيب أعلى:

import {DragDropContext} from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import TouchBackend from "react-dnd-touch-backend";

const DragAndDropHOC = props => {
    return <React.Fragment>
        {props.children}
    </React.Fragment>
};

export default {
    HTML5: DragDropContext(HTML5Backend)(DragAndDropHOC),
    Touch: DragDropContext(TouchBackend)(DragAndDropHOC),
}

ثم مكون الموفر:

const DragDrop = props => {
    if (props.isTouch) {
        return <DragDropContext.Touch>{props.children}</DragDropContext.Touch>
    } else {
        return <DragDropContext.HTML5>{props.children}</DragDropContext.HTML5>
    }
};

واستخدم <DragDrop isTouch={props.isTouch} /> أينما احتجت إليه.

للمطورين الذين واجهوا نفس المشكلة ، يمكنك إلقاء نظرة على حل HOC هذا

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

مشكلة مفصلة في SO:

https://stackoverflow.com/questions/58077693/multiple-react-dnd-jest-tests-cannot-have-two-html5-backends-at-the-same-time

باستخدام الخطافات

import { createDndContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";

const manager = useRef(createDndContext(HTML5Backend));

return (
  <DndProvider manager={manager.current.dragDropManager}>
      ....
  </DndProvider>
)

حل أفضل باستخدام الخطافات (شكرًاjchonde):

import { DndProvider, createDndContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import React, { useRef } from "react";

const RNDContext = createDndContext(HTML5Backend);

function useDNDProviderElement(props) {
  const manager = useRef(RNDContext);

  if (!props.children) return null;

  return <DndProvider manager={manager.current.dragDropManager}>{props.children}</DndProvider>;
}

export default function DragAndDrop(props) {
  const DNDElement = useDNDProviderElement(props);
  return <React.Fragment>{DNDElement}</React.Fragment>;
}

لذلك يمكنك استخدام في مكان آخر:

import DragAndDrop from "../some/path/DragAndDrop";

export default function MyComp(props){
   return <DragAndDrop>....<DragAndDrop/>
}

بلدي الحل:
اجعل المكون الفرعي لا يستورد react-dnd مباشرة.
قم بتمرير DragDropContext و HTML5Backend من مكون الأصل إلى عنصر الأطفال.

تؤدي إضافة مفتاح فريد إلى علامة DragDropContextProvider إلى حل المشكلة <DragDropContextProvider backend={HTML5Backend} key={Math. random()}></DragDropContextProvider>

في النسخة المطبوعة ، قمت بعمل المكون أدناه. (بفضلjchondettessarolo)

import { DndProvider, createDndContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import React, { PropsWithChildren, useRef } from 'react';

const RNDContext = createDndContext(HTML5Backend);

function DragAndDrop({ children }: PropsWithChildren<{}>): JSX.Element {
  const manager = useRef(RNDContext);
  return <DndProvider manager={manager.current.dragDropManager}>{children}</DndProvider>;
}

export default DragAndDrop;

واستخدمت عنصرًا كهذا

function SomeComponent(): JSX.Element {
  return (
    <DragAndDrop>
      ...
    </DragAndDrop>
  );
}

تؤدي إضافة مفتاح فريد إلى علامة DragDropContextProvider إلى حل المشكلة <DragDropContextProvider backend={HTML5Backend} key={Math. random()}></DragDropContextProvider>

عمل جيد!

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