Гид по технологиям

Как добавить перетаскивание (Drag and Drop) в React

7 min read React Обновлено 05 Jan 2026
Перетаскивание в React: методы и лучшие практики
Перетаскивание в React: методы и лучшие практики

Экран компьютера с перетаскиваемым компонентом

Веб‑интерфейсы часто выигрывают от возможности перетаскивать элементы: пользователи могут менять порядок, перемещать карточки между колонками, редактировать расположение визуально. В React есть два основных подхода:

  • нативные возможности браузера (HTML5 drag-and-drop API),
  • сторонние библиотеки, которые накрывают детали и добавляют удобства.

Ниже — упорядоченное руководство: что выбрать, как реализовать, как сделать доступно и тестируемо.

Почему важен выбор подхода

Коротко: нативный API прост для одиночных случаев, но быстро становится громоздким при сложных интерфейсах (мульти‑колонки, зеркалирование элементов, плавные анимации, мобильная поддержка и доступность). Библиотеки берут на себя работу по синхронизации позиции, коллизиям и анимациям, но добавляют зависимость и кривую обучения.

Важно: не стоит автоматически выбирать библиотеку для простых задач. Оцените сложность, требования к доступности и бюджет на поддержку.

Основные события natively (коротко)

Определения в одну строку:

  • onDragStart — начало перетаскивания; здесь обычно кладут данные в dataTransfer.
  • onDrag — повторяющееся событие во время перетаскивания.
  • onDragOver — событие при наведении на потенциальную цель; по умолчанию запрещает drop, поэтому обычно вызывают event.preventDefault().
  • onDrop — момент отпускания; здесь читают данные и обновляют состояние.
  • onDragEnd — окончание операции, используется для очистки временных данных.

Ключевые детали

  • Для того чтобы элемент был draggable, у него должен быть атрибут draggable (true по умолчанию для изображений, иначе явно). В JSX можно просто написать draggable.
  • Чтобы drop сработал, целевой контейнер должен отменять поведение по умолчанию в onDragOver: event.preventDefault().
  • Для передачи данных между элементами используется event.dataTransfer.setData/getData (обычно MIME ‘text/plain’ или собственный ключ).

Пример 1. Нативное перетаскивание (из исходника)

Ниже — код из примера (сохранён как есть). Он показывает базовые обработчики событий на классовом компоненте.

import React, { Component } from 'react';  
  
class MyComponent extends Component {  
  render() {  
    return (  
      
Drag me!
); } } export default MyComponent;

И пример методов:

import React, { Component } from 'react';  
  
class MyComponent extends Component {  
  handleDragStart(event) {  
      // This method runs when the dragging starts  
      console.log("Started")  
  }  
   
  handleDrag(event) {  
      // This method runs when the component is being dragged  
      console.log("Dragging...")  
  }  
   
  handleDragEnd(event) {  
      // This method runs when the dragging stops  
      console.log("Ended")  
  }  
   
  render() {  
    return (  
      
Drag me!
); } } export default MyComponent;

Обратите внимание: в примерах событие onDragOver на приёмнике не показано — без него drop не произойдёт.

Экран приложения React с перетаскиваемым компонентом

Перемещение элемента по координатам

Пример с хуком useState из исходника показывает, как переместить блок по координатам клиента после окончания перетаскивания:

import React, { Component, useState } from 'react';  
  
function MyComponent() {  
  const [x, setX] = useState(0);  
  const [y, setY] = useState(0);  
  
  const handleDragEnd = (event) => {  
    setX(event.clientX);  
    setY(event.clientY);  
  };  
  
  return (  
    
Drag me!
); } export default MyComponent;

Это простая техника, но имейте в виду: event.clientX/clientY дают координаты указателя, а не смещения элемента относительно контейнера, поэтому для корректного позиционирования часто нужен учёт смещения контейнера и scroll.

Пример 2. Использование сторонней библиотеки (из исходника)

Библиотека из примера — react-drag-and-drop. Пример использования:

import React, { Component } from 'react';  
import { Draggable, Droppable } from 'react-drag-and-drop';  
  
class MyComponent extends Component {  
  render() {  
    return (  
      
Drag me!
Drop here!
); } handleDrop(data, event) { // This method runs when the data drops console.log(data); // 'bar' } } export default MyComponent;

Такие обёртки упрощают API и часто добавляют свой внутренний слой для управления состоянием и анимациями.

Экран приложения React с перетаскиваемым элементом и зоной сброса

Советы по созданию удобных DnD-компонентов

  1. Визуальная обратная связь. Меняйте opacity, добавляйте тень, рамку или «флоринг» (placeholder), чтобы пользователь видел, что элемент выбран.
  2. Явно разрешайте drop с помощью onDragOver + event.preventDefault().
  3. Ограничьте допустимые группы переносимых данных (type/props или MIME) — это предотвратит некорректные операции.
  4. Дайте возможность отменить действие (Esc, кнопка «отменить», отмена drag по потере фокуса).
  5. Поддержка мобильных: HTML5 DnD плохо работает на мобильных браузерах — используйте pointer/touch события или библиотеки с мобильной поддержкой.
  6. Тестируйте на производительность при большом количестве элементов — дебаунс событий и отрисовки может понадобиться.

Когда нативный подход не подходит

  • если вам нужны плавные перестановки с анимациями (когда карточка перемещается и остальные сдвигаются плавно),
  • если требуется сложная логика сортировки между несколькими контейнерами,
  • когда нужна полноценная поддержка клавиатуры и экранных читалок без дополнительной доработки.

В таких случаях рассмотрите библиотеку.

Популярные библиотеки: плюсы и минусы

  • react-beautiful-dnd — удобна для упорядочения списков и колонок, отличные анимации; авторская библиотека Atlassian, но сейчас в состоянии кода нужно проверять совместимость с новыми версиями React.
  • react-dnd — гибкая, основана на концепции провайдеров и backend’ов (HTML5, touch); требует большего объёма кода, но даёт контроль.
  • dnd-kit — современная, модульная, с хорошей мобильной поддержкой и производительностью; активно развивается.
  • react-drag-and-drop (как в исходнике) — простая обёртка, подойдёт для базовых сценариев.

Матрица сравнения (качественная):

ЗадачаНативный APIreact-beautiful-dndreact-dnddnd-kit
Быстрая простая перетаскиваемость
Сортировка списков с анимацией✓ (сложно)
Мобильная поддержкаограниченатребует backend
Доступность (ARIA/клавиатура)вручнуювстроена частичновручнуюхорошие примеры

(Матрица качественная, проверяйте версии библиотек для совместимости с вашим стеком.)

Мини‑методология: как встроить DnD в проект (шаги)

  1. Определите требования: сортировка, мульти‑колонки, мобильность, доступность.
  2. Сделайте прототип на нативном API для оценки объёма работы.
  3. Если нужна сложность — выберите библиотеку и выполните PoC (proof of concept) для ключевых пользовательских сценариев.
  4. Реализуйте визуальную обратную связь и фоллбеки для устройств без поддержки drag.
  5. Добавьте тесты (юнит + интеграция) и проверку клавиатуры/экранных читалок.
  6. Замерьте производительность и оптимизируйте рендеринг (memo, virtualization для длинных списков).

Пример: упорядочивание списка с помощью natively (практическая реализация)

Ниже — упрощённый шаблон на хуках, реализующий перестановку списка через dataTransfer:

// Псевдокод/шаблон: суть передачи индекса через dataTransfer
function ListItem({ item, index, onDropAt }) {
  function handleDragStart(e) {
    e.dataTransfer.setData('text/plain', String(index));
  }

  function handleDrop(e) {
    e.preventDefault();
    const from = Number(e.dataTransfer.getData('text/plain'));
    onDropAt(from, index);
  }

  return (
    
e.preventDefault()}> {item.text}
); }

В коде компонент List держит массив и корректно переставляет элементы по индексам. Это простая и понятная реализация для небольших списков.

Доступность (A11y)

Короткие конкретные рекомендации:

  • Обеспечьте управление клавиатурой: кнопки перемещения (Up/Down), ловите Enter/Space для взятия/отпускания элемента.
  • Используйте aria-grabbed, role=”list” и role=”listitem” там, где уместно.
  • Сообщайте изменения через live region (aria-live) при окончании перемещения.
  • Не полагайтесь только на цветовую индикацию — добавляйте текстовые или геометрические подсказки.

Пример: при реализации сортировки добавьте небольшие «переместить вверх/вниз» кнопки для пользователей клавиатуры.

Тестирование и критерии приёмки

Критерии приёмки:

  • Элемент можно перетащить и отпустить в допустимые цели.
  • Перезапись состояния происходит корректно (проверка порядка элементов).
  • Операция отменяема (Esc или кнопка «Отмена»).
  • Визуальная обратная связь присутствует: перетаскиваемый элемент легко идентифицировать.
  • Клавиатурная навигация позволяет выполнить те же операции.

Тесты:

  • Юнит: имитировать события onDragStart/onDrop и проверить изменение состояния.
  • Интеграция: end‑to‑end тест с Cypress/Playwright — проверка поведения в реальном браузере.
  • Accessibility: автоматический аудит (axe) + ручная проверка клавиатуры.

Чек‑лист по ролям

Для разработчика:

  • Есть PoC для ключевых сценариев.
  • Реализована отмена и обработка ошибок.
  • Добавлены unit и e2e тесты.

Для дизайнера:

  • Даны состояния перетаскивания (hover, dragging, drop target).
  • Есть фоллбеки для цветовой слепоты и малого размера шрифта.

Для продуктового менеджера:

  • Оценено влияние на мобильных пользователях.
  • Согласовано поведение при конфликтных действиях (несколько пользователей).

Риски и смягчения

  • Риск: плохая мобильная поддержка — Смягчение: использовать библиотеку с pointer/touch поддержкой (dnd-kit) или реализовать touch fallback.
  • Риск: проблемы с доступностью — Смягчение: добавить клавиатурные контролы и тесты с screen reader.
  • Риск: производительность при 100+ элементах — Смягчение: виртуализировать список, ограничить частоту обновлений.

Когда выбирать библиотеку

Выбирайте библиотеку, если хотя бы одно из условий истинно:

  • Нужна сложная перестановка с анимациями.
  • Требуется поддержка drag между несколькими списками/колонками.
  • Нужно готовое решение для доступности.

Короткая сводка

  • Начинайте с оценки требований и PoC.
  • Нативный API хорош для простых случаев, но требует ручной доработки для доступа, мобильности и анимаций.
  • Библиотеки ускоряют разработку сложных интерфейсов, но добавляют зависимость и могут требовать миграции при обновлениях.
  • Обязательно тестируйте поведение клавиатурой и на мобильных устройствах.

Важно: перетаскивание — мощный UX‑инструмент, но он должен быть предсказуемым, доступным и отзывчивым.

Краткое резюме

  • Перетаскивание в React можно сделать нативно или с библиотекой.
  • Нативный подход прост для одиночных элементов.
  • Для сложных сценариев используйте react-beautiful-dnd, react-dnd или dnd-kit.
  • Не забывайте про доступность, мобильные устройства и тесты.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство