React-dnd: HTML5Backend прекращает перетаскивание, когда в DOM появляются/исчезают элементы в событии перетаскивания: CHROME

Созданный на 1 апр. 2020  ·  3Комментарии  ·  Источник: react-dnd/react-dnd

Опишите ошибку
У нас серьезная проблема с html5backend. Нам нужно создать несколько промежутков, чтобы указать пользователю, куда перетащить перетаскиваемый элемент, мы хотим, чтобы эти промежутки были видны только во время перетаскивания элемента.
В firefox работает отлично, но в chrome карты запускают событие остановки перетаскивания сразу после события начала перетаскивания.

Воспроизведение
https://codesandbox.io/s/react-dnd-sortable-holes-bq2oe
Каждую карту можно перетаскивать, и когда пользователь начинает перетаскивать, появляются оранжевые промежутки.
image

image

В firefox работает как шарм, но в chrome событие остановки запускается сразу после события запуска.

Как вы можете видеть в консоли:
image

  • ОС: [например, iOS]
  • Браузер: ошибка в Chrome версии 80.0.3987.162, отлично работает в Firefox 74.0 (64-разрядная версия)

Любая помощь будет очень признательна, нам действительно нужна эта функциональность.

Самый полезный комментарий

Наша команда улучшила обходной путь состояния, создав собственный хук для провайдера перетаскивания. В любом случае, если кто-то из вас столкнется с этой проблемой, вот решение, пока ошибка устранена.

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

Основная часть состоит в определении контекста и поставщика для хранения статуса перетаскивания.

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

Во-вторых, используя setTimeout в функции начала перетаскивания, можно избежать отправки конца.

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

И, наконец, собранное значение isDragging перезаписывается значением контекста.

Все 3 Комментарий

Я нашел обходной путь, много читал, для этой проблемы, установка таймаута и переменной состояния, которую я передаю через компоненты, мне это не очень нравится, потому что в этих простых случаях это легко сделать, но в сложных случаях я должен использовать контекст или что-то подобное, чтобы все работало.
https://codesandbox.io/s/react-dnd-sortable-holes-vxeus

Я надеюсь, что вы сможете найти лучшее решение, я бы хотел использовать isDragging из библиотеки вместо этого обходного пути.

Наша команда улучшила обходной путь состояния, создав собственный хук для провайдера перетаскивания. В любом случае, если кто-то из вас столкнется с этой проблемой, вот решение, пока ошибка устранена.

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

Основная часть состоит в определении контекста и поставщика для хранения статуса перетаскивания.

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

Во-вторых, используя setTimeout в функции начала перетаскивания, можно избежать отправки конца.

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

И, наконец, собранное значение isDragging перезаписывается значением контекста.

У кого-нибудь есть решение или идея исправления этой проблемы, которое не включает такой обходной путь?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги