useDrop для зон сбрасывания

Хук useDrop является ключевым инструментом библиотеки React Aria для реализации функционала drag-and-drop. Он позволяет создавать зоны сбрасывания, которые корректно взаимодействуют с элементами перетаскивания, управляют состояниями и обеспечивают доступность (accessibility) интерфейса.

useDrop предоставляет набор свойств и колбеков, которые позволяют:

  • Определять, какие элементы могут быть сброшены на целевую область.
  • Отслеживать состояния наведения, активации и выполнения сброса.
  • Обеспечивать корректную работу с клавиатурой и вспомогательными технологиями.
import {useDrop} from '@react-aria/dnd';
import {useRef} from 'react';

function DropZone({onDrop}) {
  const ref = useRef();
  const {dropProps, isDropTarget} = useDrop({
    onDrop,
    accepts: ['text', 'image'],
  }, ref);

  return (
    <div {...dropProps} ref={ref} style={{border: isDropTarget ? '2px solid blue' : '2px dashed gray', padding: '20px'}}>
      Перетащите сюда элементы
    </div>
  );
}

Параметры useDrop

  1. onDrop – функция, вызываемая при успешном сбросе элемента. Получает объект с данными перетаскиваемого элемента.
  2. accepts – массив типов данных, которые зона готова принимать. Позволяет фильтровать элементы по их типу.
  3. onEnter – колбек, срабатывающий при наведении перетаскиваемого элемента на зону. Используется для визуальной подсветки или подготовки состояния.
  4. onLeave – вызывается при уходе элемента с зоны сброса, часто используется для отмены визуальных эффектов наведения.
  5. onDropChange – срабатывает при изменении состояния сброса, например, когда элемент стал допустимым для броска.

Состояния зоны сброса

useDrop предоставляет объект состояния с ключевыми флагами:

  • isDropTargettrue, если в данный момент на зону наведён элемент, подходящий для сброса.
  • isActivetrue, когда элемент перетаскивается и зона готова принять его.
  • dropEffect – определяет действие, которое будет выполнено (copy, move, link).

Эти состояния позволяют динамически изменять стили зоны, обеспечивая визуальную обратную связь.

<div
  {...dropProps}
  ref={ref}
  style={{
    border: isDropTarget ? '2px solid green' : '2px dashed gray',
    backgroundColor: isActive ? '#e0ffe0' : '#fff',
    padding: '20px'
  }}
>
  Перетащите элемент сюда
</div>

Интеграция с useDrag

Для полноценной системы drag-and-drop зоны сброса часто комбинируются с элементами, использующими useDrag. Взаимодействие осуществляется через типы данных:

import {useDrag} from '@react-aria/dnd';

function DraggableItem({type, data}) {
  const ref = useRef();
  const {dragProps} = useDrag({
    type,
    getItems: () => [{...data}],
  }, ref);

  return (
    <div {...dragProps} ref={ref} style={{padding: '10px', border: '1px solid black'}}>
      Перетащи меня
    </div>
  );
}

Важно, чтобы accepts в зоне сброса совпадал с type элемента, иначе сброс не будет возможен.

Поддержка доступности (Accessibility)

React Aria обеспечивает автоматическую поддержку доступности для зон сброса:

  • Элементы могут быть доступны через клавиатуру с использованием стрелок и клавиши Enter для сброса.
  • Используются ARIA-атрибуты (aria-dropeffect, aria-describedby), которые помогают вспомогательным технологиям сообщать о возможности сброса.
  • Состояния isDropTarget и isActive могут использоваться для предоставления визуальных и текстовых подсказок.

Советы по стилям и UX

  • Всегда визуально обозначать активную зону сброса, чтобы пользователь понимал, куда можно сбросить элемент.
  • Использовать плавные анимации изменения границ или фона при наведении элемента.
  • Предусматривать разные визуальные эффекты для допустимых и недопустимых типов данных.
style={{
  border: isDropTarget ? '2px solid green' : '2px dashed gray',
  backgroundColor: isActive ? '#f0fff0' : isDropTarget ? '#ffffe0' : '#fff'
}}

Комплексные сценарии

useDrop поддерживает множественные типы элементов и вложенные зоны. Например, можно создать иерархию зон, где родительская зона принимает только контейнеры, а дочерняя – отдельные элементы. Для этого используется проверка accepts и логика в onDrop.

const {dropProps, isDropTarget} = useDrop({
  onDrop: handleDrop,
  accepts: ['container', 'item'],
  onEnter: (item) => console.log('Наведение', item.type),
});

Такой подход позволяет строить гибкие интерфейсы с drag-and-drop, включая списки, сетки и сложные панели с поддержкой доступности.


useDrop обеспечивает мощный и гибкий способ работы с зонами сброса в React Aria, позволяя создавать безопасные, доступные и интуитивно понятные интерфейсы для пользователей.