React-dnd: HTML5Backend stoppt das Ziehen, wenn Elemente im DOM erscheinen/verschwinden im Drag-Event: CHROME

Erstellt am 1. Apr. 2020  ·  3Kommentare  ·  Quelle: react-dnd/react-dnd

Beschreiben Sie den Fehler
Wir haben ein ernsthaftes Problem mit dem HTML5-Backend. Wir müssen einige Lücken erzeugen, um den Benutzer zu führen, wo das gezogene Element abgelegt werden soll. Wir möchten, dass diese Lücken nur sichtbar sind, während das Element gezogen wird.
In Firefox funktioniert es perfekt, aber in Chrome starten die Karten das Stop-Dragging-Ereignis unmittelbar nach dem Start-Draging-Ereignis.

Reproduktion
https://codesandbox.io/s/react-dnd-sortable-holes-bq2oe
Jede Karte kann gezogen werden, und wenn der Benutzer mit dem Ziehen beginnt, erscheinen orangefarbene Lücken.
image

image

In Firefox funktioniert es wie ein Zauber, aber in Chrome wird das Stop-Event sofort nach dem Start-Event gestartet.

Wie Sie in der Konsole sehen können:
image

  • Betriebssystem: [zB iOS]
  • Browser: Bug in Chrome Version 80.0.3987.162, funktioniert perfekt in Firefox 74.0 (64-bit)

Jede Hilfe wird sehr geschätzt, wir brauchen diese Funktionalität wirklich.

Hilfreichster Kommentar

Unser Team hat die Statusumgehung verbessert und einen benutzerdefinierten Hook für den Drag-and-Drop-Anbieter erstellt. Falls jemand von Ihnen mit diesem Problem konfrontiert ist, finden Sie hier eine Lösung, während der Fehler behoben ist.

https://codesandbox.io/s/react-dnd-sortable-gaps-custom-9tl13

Der Hauptteil besteht darin, einen Kontext und einen Anbieter zu definieren, um den Ziehstatus zu speichern.

const DndContext = React.createContext([{}, () => {}]);

const DndCustomProvider = props => {
  const [state, setState] = useState({ dragging: false });

  return (
    <DndProvider backend={props.backend}>
      <DndContext.Provider value={[state, setState]}>
        {props.children}
      </DndContext.Provider>
    </DndProvider>
  );
};

Zweitens wird durch die Verwendung von setTimeout in der Drag-Beginn-Funktion das ausgelöste Ende vermieden.

  const [context, setContext] = useContext(DndContext);

  const [collected, dragRef] = useDrag({
    ...,
    begin: monitor => {
      setTimeout(() => {
        setContext(() => ({ dragging: true }));
      }, 0);

      if (begin) {
        begin(monitor);
      }
    },
    end: (item, monitor) => {
      setContext(() => ({ dragging: false }));

      if (end) {
        end(item, monitor);
      }
    },
    ...
  });

  return [
    {
      ...collected,
      isDragging: context.dragging
    },
    dragRef
  ];

Und schließlich wird der gesammelte Wert von isDragging mit dem Kontextwert überschrieben.

Alle 3 Kommentare

Ich habe eine Problemumgehung gefunden, viel gelesen, für dieses Problem, ein Timeout und eine Zustandsvariable festgelegt, die ich durch Komponenten leite, ich mag es nicht sehr, weil es in diesen einfachen Fällen einfach zu tun ist, aber komplex Fällen sollte ich Kontext oder ähnliches verwenden, damit alles funktioniert.
https://codesandbox.io/s/react-dnd-sortable-holes-vxeus

Ich hoffe, dass Sie mich durch eine bessere Lösung führen können. Ich möchte anstelle dieser Problemumgehung das isDragging aus der Bibliothek verwenden.

Unser Team hat die Statusumgehung verbessert und einen benutzerdefinierten Hook für den Drag-and-Drop-Anbieter erstellt. Falls jemand von Ihnen mit diesem Problem konfrontiert ist, finden Sie hier eine Lösung, während der Fehler behoben ist.

https://codesandbox.io/s/react-dnd-sortable-gaps-custom-9tl13

Der Hauptteil besteht darin, einen Kontext und einen Anbieter zu definieren, um den Ziehstatus zu speichern.

const DndContext = React.createContext([{}, () => {}]);

const DndCustomProvider = props => {
  const [state, setState] = useState({ dragging: false });

  return (
    <DndProvider backend={props.backend}>
      <DndContext.Provider value={[state, setState]}>
        {props.children}
      </DndContext.Provider>
    </DndProvider>
  );
};

Zweitens wird durch die Verwendung von setTimeout in der Drag-Beginn-Funktion das ausgelöste Ende vermieden.

  const [context, setContext] = useContext(DndContext);

  const [collected, dragRef] = useDrag({
    ...,
    begin: monitor => {
      setTimeout(() => {
        setContext(() => ({ dragging: true }));
      }, 0);

      if (begin) {
        begin(monitor);
      }
    },
    end: (item, monitor) => {
      setContext(() => ({ dragging: false }));

      if (end) {
        end(item, monitor);
      }
    },
    ...
  });

  return [
    {
      ...collected,
      isDragging: context.dragging
    },
    dragRef
  ];

Und schließlich wird der gesammelte Wert von isDragging mit dem Kontextwert überschrieben.

Hat jemand eine Lösung oder eine Idee für einen Patch für dieses Problem, der keine solche Problemumgehung beinhaltet?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen