DOM и React Senior Компоненты на практике обновлено

Канбан с перетаскиванием

Условие

Доска из колонок { id, title, cards: [{ id, text }] }. Требования: · колонка - <div class="col" data-col>, карточка - <div class="card" data-card draggable>; · перетаскивание карточки в другую колонку переносит её туда; · dragover у колонки обязан отменяться, иначе сброс не сработает; · бросок в ту же колонку ничего не меняет; · onMove(cardId, fromCol, toCol) при успешном переносе; · счётчик карточек в колонке - <span class="count">.

Что проверяют тесты

  • рисует доску

  • переносит карточку

  • dragover отменяется

  • бросок в ту же колонку ничего не меняет

  • сообщает о переносе наружу

  • исходные данные не мутируются

Как подойти

Главный подвох нативного перетаскивания в том, что элемент по умолчанию не является зоной сброса: без отмены поведения по умолчанию у dragover событие drop просто не придёт. Второе решение - держать перетаскиваемую карточку в ref, а не в состоянии: она не влияет на отрисовку, и лишние рендеры во время перетаскивания только мешают. Перенос делается одним map по колонкам, чтобы удаление и вставка произошли в одном обновлении. Что назвать вслух: вставка в позицию, а не в конец, подсветка зоны сброса, доступная альтернатива клавиатурой, dataTransfer для переноса между окнами.

Подсказки: 3
  1. Что именно тащат, храни в ref: это не влияет на отрисовку.
  2. Без preventDefault на dragover событие drop не наступит вовсе.
  3. Перенос - это одно неизменяемое обновление всего списка колонок.

Решите в тренажёре

Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.