React-dnd: HTML5Backend deja de arrastrar cuando hay elementos en el DOM que aparecen/desaparecen en el evento de arrastre: CHROME

Creado en 1 abr. 2020  ·  3Comentarios  ·  Fuente: react-dnd/react-dnd

Describa el error
Tenemos un problema serio con el html5backend. Necesitamos generar algunos espacios para guiar al usuario a dónde soltar el elemento arrastrado, queremos que esos espacios solo sean visibles mientras se arrastra el elemento.
En firefox funciona perfecto, pero en chrome, las tarjetas lanzan el evento de parada de arrastre inmediatamente después del evento de inicio de arrastre.

Reproducción
https://codesandbox.io/s/react-dnd-sortable-holes-bq2oe
Cada tarjeta se puede arrastrar y cuando el usuario comienza a arrastrar, aparecen espacios naranjas.
image

image

En Firefox funciona a las mil maravillas, pero en Chrome, el evento de parada se inicia inmediatamente después del evento de inicio.

Como se puede ver en la consola:
image

  • SO: [por ejemplo, iOS]
  • Navegador: Error en Chrome Versión 80.0.3987.162, funciona perfecto en firefox 74.0 (64-bit)

Cualquier ayuda será muy apreciada, realmente necesitamos esta funcionalidad.

Comentario más útil

Nuestro equipo ha mejorado la solución del estado creando un enlace personalizado para el proveedor de arrastrar y soltar, en cualquier caso, si alguno de ustedes enfrenta este problema, aquí hay una solución mientras se resuelve el error.

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

La parte principal consiste en definir un Contexto y un Proveedor para almacenar el estado de arrastre.

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

En segundo lugar, al usar setTimeout en la función de inicio de arrastre, se evita el envío del final.

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

Y finalmente, el valor recopilado de isDragging se sobrescribe con el valor de contexto.

Todos 3 comentarios

Encontré una solución, leyendo mucho, para este problema, establecer un tiempo de espera y una variable de estado que paso a través de los componentes, no me gusta mucho, porque en estos casos simples es fácil de hacer, pero en complejos casos, debería usar context o algo similar para que todo funcione.
https://codesandbox.io/s/react-dnd-sortable-holes-vxeus

Espero que pueda guiarme a través de una mejor solución, me gustaría usar isDragging de la biblioteca en lugar de esta solución.

Nuestro equipo ha mejorado la solución del estado creando un enlace personalizado para el proveedor de arrastrar y soltar, en cualquier caso, si alguno de ustedes enfrenta este problema, aquí hay una solución mientras se resuelve el error.

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

La parte principal consiste en definir un Contexto y un Proveedor para almacenar el estado de arrastre.

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

En segundo lugar, al usar setTimeout en la función de inicio de arrastre, se evita el envío del final.

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

Y finalmente, el valor recopilado de isDragging se sobrescribe con el valor de contexto.

¿Alguien tiene una solución o una idea para un parche para este problema que no implique una solución alternativa?

¿Fue útil esta página
0 / 5 - 0 calificaciones