Хук useDrag предоставляет механизм для создания
доступных перетаскиваемых элементов в приложениях на React. Он
абстрагирует низкоуровневую работу с событиями мыши, сенсорными экранами
и клавиатурой, обеспечивая совместимость с ARIA-стандартами.
import {useDrag} from '@react-aria/dnd';
import {useRef} from 'react';
function DraggableItem({item}) {
let ref = useRef();
let {dragProps} = useDrag({
id: item.id,
type: 'item',
});
return (
<div ref={ref} {...dragProps}>
{item.name}
</div>
);
}
id — уникальный идентификатор
перетаскиваемого элемента. Используется для отслеживания состояния
перетаскивания.type — тип элемента, важен при работе
с useDrop для фильтрации совместимых целей.dragProps — набор пропсов, которые
необходимо распространить на корневой элемент для корректной работы
перетаскивания.Хук возвращает объект с основными свойствами:
isDragging — булевое значение,
указывающее, перетаскивается ли элемент в данный момент.dragProps — обработчики событий и
атрибуты ARIA.Пример использования состояния для визуальной индикации:
function DraggableItem({item}) {
let ref = useRef();
let {dragProps, isDragging} = useDrag({
id: item.id,
type: 'item',
});
return (
<div
ref={ref}
{...dragProps}
style={{
opacity: isDragging ? 0.5 : 1,
cursor: 'grab',
}}
>
{item.name}
</div>
);
}
useDrag автоматически поддерживает:
Можно переопределить поведение с помощью колбэков:
onDragStart — вызывается при начале
перетаскивания.onDragEnd — вызывается после
завершения перетаскивания.onDragMove — срабатывает при каждом
перемещении элемента.Пример расширенного управления:
let {dragProps, isDragging} = useDrag({
id: item.id,
type: 'item',
onDragStart: () => console.log('Начало перетаскивания', item.id),
onDragMove: (position) => console.log('Текущая позиция', position),
onDragEnd: (result) => console.log('Завершено', result),
});
useDropПеретаскиваемый элемент в паре с зоной сброса (useDrop)
позволяет реализовать полноценные списки, сетки и канбан-доски. Важно
указывать совместимый type, чтобы
ограничить допустимые цели.
Пример зоны сброса:
import {useDrop} from '@react-aria/dnd';
function DropZone({onDrop}) {
let ref = useRef();
let {dropProps, isDropTarget} = useDrop({
accept: 'item',
onDrop: (draggedItem) => onDrop(draggedItem),
});
return (
<div
ref={ref}
{...dropProps}
style={{
background: isDropTarget ? 'lightblue' : 'transparent',
minHeight: '100px',
border: '1px dashed gray',
}}
>
Перетащите сюда элемент
</div>
);
}
ref на корневом элементе
— React Aria требует прямой ссылки на DOM-узел.useDrag
автоматически добавляет атрибуты aria-grabbed и роль
button/listitem.opacity,
cursor или теней.useDrag отдельно от визуальных компонентов для
тестируемости.Для больших приложений можно обернуть список перетаскиваемых элементов в контекст Drag-and-Drop, чтобы управлять состоянием глобально:
import {DragDropProvider} from '@react-aria/dnd';
function App() {
return (
<DragDropProvider>
<DraggableList items={items} />
</DragDropProvider>
);
}
Это позволяет отслеживать активный элемент, блокировать одновременное перетаскивание нескольких объектов и упрощает реализацию комплексных интерфейсов, таких как доски задач или редакторы списков.
useDrag не управляет позицией элемента на экране. Для
этого требуется отдельная логика или интеграция с библиотекой визуальной
анимации (framer-motion, react-spring).id для корректной
работы событий onDragEnd.useDrag предоставляет мощный, полностью доступный способ
реализовать перетаскивание элементов в React-приложениях, упрощая работу
с различными устройствами ввода и обеспечивая совместимость с
ARIA-стандартами.