Как реализовать функциональность перетаскивания с помощью React Beautiful Dnd

Мир бесшовных взаимодействий: магия перетаскивания

Представьте себе следующее: вы используете приложение для управления проектами, без усилий перетаскивая задачи своей команды из одной колонки в другую по мере изменения приоритетов. Это плавное взаимодействие кажется почти волшебным и к тому же создает интуитивно понятный и визуально привлекательный пользовательский опыт. Но задумывались ли вы когда-нибудь, как можно воссоздать это волшебство в собственных React-приложениях? Вот тут-то на помощь приходит React Beautiful Dnd  —  библиотека, которая позволяет легко реализовать функциональность перетаскивания.

В этой статье мы совершим глубокое погружение в мир библиотеки React Beautiful Dnd. Я расскажу о том, как она может преобразить веб-приложения, добавив бесшовное и визуально привлекательное взаимодействие перетаскивания (drag-and-drop). Это руководство будет полезно как опытным React-разработчикам, так и новичкам, желающим расширить свой набор навыков. Оно вооружит вас знаниями и инструментами, необходимыми для создания интерактивных веб-приложений, которые порадуют пользователей.

Приготовьтесь овладеть искусством создания операций перетаскивания с использованием возможностей библиотеки React Beautiful Dnd!


Настройка среды

Закладываем фундамент: необходимый инструментарий

Перед погружением в мир React Beautiful Dnd необходимо настроить среду разработки. Мы вместе пошагово пройдем этот процесс, и вы сможете быстро приступить к реализации функциональности перетаскивания. К концу этого раздела у вас под рукой будут все необходимые инструменты и программное обеспечение, готовые к созданию чего-то необычного.

Подготовка среды разработки

Прежде всего убедитесь в том, что на вашем компьютере установлено следующее программное обеспечение:

  • Node.js (версия 10 или выше). Node.js  —  это среда разработки, позволяющая выполнять JavaScript-код на стороне сервера. Вы можете загрузить Node.js с официального сайта.
  • Редактор кода на ваш выбор. Рекомендую Visual Studio Code, но подойдет и другой редактор.

Создание нового React-проекта

Теперь, когда среда разработки готова, пришло время создать новый React-проект. Откройте терминал или командную строку и выполните следующую команду:

npx create-react-app my-dnd-app

Эта команда создаст новую папку my-dnd-app, содержащую шаблонное React-приложение. Вы можете заменить “my-dnd-app” на любое имя проекта.

Установка React Beautiful Dnd

Настроив React-проект, приступим к установке библиотеки React Beautiful Dnd. Перейдите в папку проекта с помощью терминала или командной строки:

cd my-dnd-app

Затем выполните следующую команду для установки библиотеки:

npm install react-beautiful-dnd

Вы успешно установили React Beautiful Dnd и готовы приступить к изучению возможностей этой библиотеки.

Настройка редактора кода

Прежде чем погрузиться в код, убедитесь, что редактор кода правильно настроен для плавной разработки. Если вы используете Visual Studio Code, рекомендую установить следующие расширения:

  • ESLint. Помогает поддерживать единый стиль кода и выявлять потенциальные проблемы на ранних стадиях.
  • Prettier. Автоматически форматирует код, сохраняя его чистым и читабельным.
  • Babel JavaScript. Улучшает подсветку синтаксиса JavaScript и автодополнение.

Вы можете устанавливать дополнительные расширения, соответствующие вашим предпочтениям и рабочему процессу.

Теперь среда полностью готова к реализации функциональности перетаскивания с помощью React Beautiful Dnd. В следующем разделе я представлю ключевые компоненты библиотеки и расскажу, как они взаимодействуют друг с другом.


Основы React Beautiful Dnd

В этом разделе погрузимся в основы React Beautiful Dnd  —  мощной библиотеки, которая позволяет легко создавать интуитивно понятные взаимодействия перетаскивания в приложениях React.

Рассмотрим ключевые компоненты, которые образуют строительные блоки библиотеки (Draggable, Droppable и DragDropContext), и изучим, как они работают вместе, чтобы создать бесшовный пользовательский опыт.

Основные компоненты

React Beautiful Dnd предлагает три основных компонента:

  • Draggable. Представляет отдельные элементы, которые можно перетаскивать.
  • Droppable. Определяет области, в которые можно опускать перетаскиваемые элементы.
  • DragDropContext. Компонент верхнего уровня, управляющий общим состоянием и координирующий взаимодействие между компонентами Draggable и Droppable.

Рассмотрим каждый компонент подробно.

Draggable

Draggable  —  основной компонент любого взаимодействия перетаскивания. Он оборачивается вокруг любого элемента, который вы хотите сделать перетаскиваемым. Предоставляя элементу уникальный id и индекс, React Beautiful Dnd знает, как управлять его положением в процессе перетаскивания.

<Draggable draggableId="uniqueId" index={0}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
Здесь находится контент draggable
</div>
)}
</Draggable>

Droppable

Компонент Droppable представляет drop-зоны  —  области, куда пользователи могут переместить элементы Draggable. Для каждого Droppable требуется уникальный droppableId. Вам также нужно будет предоставить функцию, которая возвращает соответствующую разметку для drop-зоны.

<Droppable droppableId="uniqueId">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{/* Компоненты Draggable будут вставлены сюда */}
{provided.placeholder}
</div>
)}
</Droppable>

DragDropContext

Компонент DragDropContext действует как обертка верхнего уровня для всей системы перетаскивания. Он управляет глобальным состоянием и координирует взаимодействие между компонентами Draggable и Droppable. Вам необходимо предоставить функцию обратного вызова onDragEnd, которая вызывается, когда операция перетаскивания завершена. Здесь вам нужно обновить состояние приложения, чтобы отразить новый порядок элементов.

<DragDropContext onDragEnd={handleDragEnd}>
{/* Компоненты Draggable и Droppable помещаются сюда */}
</DragDropContext>

Взаимодействие компонентов

Теперь посмотрим, как эти компоненты взаимодействуют друг с другом. Когда пользователь начинает перетаскивать Draggable-элемент, компонент DragDropContext прослушивает событие перетаскивания и соответствующим образом обновляет свое внутреннее состояние. Когда пользователь перемещает элемент в Droppable-область, компонент Droppable взаимодействует с DragDropContext, чтобы определить, можно ли опустить элемент туда.

Как только пользователь отпускает элемент, срабатывает функция обратного вызова onDragEnd. Здесь вы обновляете состояние приложения, чтобы отразить новый порядок элементов Draggable. React Beautiful Dnd берет на себя все сложные вычисления и анимацию, позволяя сосредоточиться на реализации желаемой функциональности.


Простой пример: создание доски задач

В этом разделе рассмотрим процесс создания базовой доски задач с помощью React Beautiful Dnd.

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

Шаг 1. Создание компонентов доски задач

Сначала создадим несколько компонентов, которые будут представлять доску задач, колонки и задачи. В каталоге src создадим новую папку с названием components и добавим в нее три новых файла: TaskBoard.js, Column.js и Task.js. Начнем с создания компонента Task в файле Task.js:

import React from 'react';

const Task = ({ task }) => {
return (
<div className="task">
{task.content}
</div>
);
};

export default Task;

В файле Column.js создадим простой компонент колонок, отображающий дочерние задачи:

import React from 'react';
import Task from './Task';

const Column = ({ column, tasks }) => {
return (
<div className="column">
<h3>{column.title}</h3>
<div className="task-list">
{tasks.map(task => <Task key={task.id} task={task} />)}
</div>
</div>
);
};

export default Column;

Наконец, создадим компонент TaskBoard в TaskBoard.js, который будет отображать несколько колонок:

import React from 'react';
import Column from './Column';

const TaskBoard = ({ data }) => {
return (
<div className="task-board">
{data.columnOrder.map(columnId => {
const column = data.columns[columnId];
const tasks = column.taskIds.map(taskId => data.tasks[taskId]);
return <Column key={column.id} column={column} tasks={tasks} />;
})}
</div>
);
};

export default TaskBoard;

Шаг 2. Интеграция React Beautiful Dnd

Теперь, когда у нас есть основные компоненты, интегрируем React Beautiful Dnd, чтобы включить функцию перетаскивания. Сначала импортируем необходимые компоненты (верхняя часть TaskBoard.js):

import { DragDropContext, Droppable } from 'react-beautiful-dnd';

Затем обернем всю доску задач в компонент DragDropContext, который будет управлять общим состоянием перетаскивания:

const TaskBoard = ({ data }) => {
return (
<DragDropContext>
{/* ... */}
</DragDropContext>
);
};

В Column.js обернем список задач в компонент Droppable, который определяет области, куда можно опускать задачи:

import { Droppable } from 'react-beautiful-dnd';

// ...

const Column = ({ column, tasks }) => {
return (
<div className="column">
<h3>{column.title}</h3>
<Droppable droppableId={column.id}>
{(provided) => (
<div
className="task-list"
ref={provided.innerRef}
{...provided.droppableProps}
>
{tasks.map(task => <Task key={task.id} task={task} />)}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
);
};

Наконец, обновим Task.js, чтобы обернуть содержимое задач в компонент Draggable, который позволяет брать и перемещать задачи:

import { Draggable } from 'react-beautiful-dnd';

// ...

const Task = ({ task, index }) => {
return (
<Draggable draggableId={task.id} index={index}>
{(provided) => (
<div
className="task"
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{task.content}
</div>
)}
</Draggable>
);
};

Не забудьте передать свойство index из компонента Column в компонент Task, поскольку оно требуется компоненту Draggable:

// Column.js
{tasks.map((task, index) => (
<Task key={task.id} task={task} index={index} />
))}

Шаг 3. Реализация обработчиков событий перетаскивания

Для обработки событий перетаскивания понадобится определить функцию, которая будет обрабатывать событие onDragEnd в компоненте TaskBoard. Эта функция будет отвечать за обновление порядка задач при завершении операции перетаскивания:

import { useState } from 'react';

// ...
const TaskBoard = ({ data }) => {
const [boardData, setBoardData] = useState(data);

const onDragEnd = (result) => {
// Внедрение логики для обновления порядка задач
};

return (
<DragDropContext onDragEnd={onDragEnd}>
{/* ... */}
</DragDropContext>
);
};

Внутри функции onDragEnd проверим, была ли операция перетаскивания успешной, и соответствующим образом обновим порядок задач:

const onDragEnd = (result) => {
const { destination, source, draggableId } = result;

if (!destination) {
return;
}
if (
destination.droppableId === source.droppableId &&
destination.index === source.index
) {
return;
}

const column = boardData.columns[source.droppableId];
const newTaskIds = Array.from(column.taskIds);
newTaskIds.splice(source.index, 1);
newTaskIds.splice(destination.index, 0, draggableId);

const newColumn = {
...column,
taskIds: newTaskIds,
};

const newBoardData = {
...boardData,
columns: {
...boardData.columns,
[newColumn.id]: newColumn,
},
};

setBoardData(newBoardData);
};

Шаг 4. Настройка и стилизация

Теперь, когда доска задач имеет функцию перетаскивания, настройте и стилизуйте ее в соответствии со своими предпочтениями. Используйте CSS для стилизации компонентов и придания им визуальной привлекательности. Можно, к примеру, добавить плавные переходы при перетаскивании, настроить цвета и шрифты или добавить эффекты для курсора, чтобы повысить удобство работы.

Теперь перейдем к изучению дополнительных возможностей React Beautiful Dnd, таких как перетаскивание между несколькими колонками и создание более сложных расположений.


Расширенные возможности и примеры использования

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

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

Множественные Droppable-области

React Beautiful Dnd позволяет легко поддерживать несколько Droppable-областей в приложении. Чтобы добиться этого, создайте дополнительные компоненты Droppable и обеспечьте им уникальные значения droppableId.

Эта функция может быть особенно полезна, когда необходимо реализовать доску Kanban или перемещать элементы между списками, например переносить задачи из списка намеченных дел в список выполненных.

/* Пример множественных Droppable-областей */
<Droppable droppableId="droppable1">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{/* Render draggable items here */}
{provided.placeholder}
</div>
)}
</Droppable>
<Droppable droppableId="droppable2">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{/* Render draggable items here */}
{provided.placeholder}
</div>
)}
</Droppable>

Условное перемещение

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

/* Пример условного перемещения */
<Droppable droppableId="droppable1" isDropDisabled={isDropDisabled}>
{/* ... */}
</Droppable>

Пользовательские обработчики перетаскивания

React Beautiful Dnd позволяет создавать пользовательские обработчики перетаскивания для улучшения пользовательского опыта. По умолчанию в качестве обработчика перетаскивания выступает вся перетаскиваемая область, но вы можете выбрать определенную часть компонента в качестве обработчика перетаскивания с помощью dragHandleProps, предоставляемых компонентом Draggable.

/* Пример пользовательского обработчика перетаскивания */
<Draggable draggableId="draggable1" index={0}>
{(provided) => (
<div ref={provided.innerRef} {...provided.draggableProps}>
{/* Render the drag handle */}
<div {...provided.dragHandleProps}>Drag Handle</div>
{/* Rest of the content */}
</div>
)}
</Draggable>

Перетаскивание между списками с разными типами

Если вам нужно реализовать взаимодействие перетаскивания между списками с разными типами, React Beautiful Dnd поможет вам в этом. Вы можете установить свойство type для компонента Droppable, чтобы различать списки и предотвратить попадание элементов не в тот список.

/* Пример перетаскивания между списками с разными типами */
<Droppable droppableId="droppable1" type="TYPE_A">
{/* ... */}
</Droppable>
<Droppable droppableId="droppable2" type="TYPE_B">
{/* ... */}
</Droppable>

Оптимизация производительности

Для больших списков производительность может быть проблемой, но React Beautiful Dnd предоставляет возможности для оптимизации. Можно использовать технику, называемую windowing (управление окнами), которая предполагает отображение только подмножества элементов списка в зависимости от позиции прокрутки пользователя. Сторонние библиотеки, такие как react-window и react-virtualized, помогут реализовать “оконный” режим в приложении.

/* Пример оптимизации производительности (с использованием react-window) */
import { FixedSizeList as List } from 'react-window';

<List
height={500}
itemCount={items.length}
itemSize={75}
width={300}
>
{({ index, style }) => (
<Draggable key={items[index].id} draggableId={items[index].id} index={index}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{ ...provided.draggableProps.style, ...style }}
>
{/* Render item content */}
</div>
)}
</Draggable>
)}
</List>

Доступность

React Beautiful Dnd поставляется со встроенной поддержкой клавиатуры, что делает взаимодействие с перетаскиванием доступным для пользователей, предпочитающих клавиатурную навигацию. Она также поддерживает скринридеры для пользователей с нарушениями зрения.


Заключение

Вы изучили основы React Beautiful Dnd и создали доску задач. Знание ключевых компонентов  —  Draggable, Droppable и DragDropContext  —  позволит создавать бесшовные взаимодействия перетаскивания для React-приложений.

Однако это только начало. Изучите другие возможности и примеры использования, чтобы адаптировать опыт перетаскивания в своих приложениях.

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Anto Semeraro: Implement Drag and Drop Functionality in React

Предыдущая статьяКак автоматизировать удаление ненужных файлов с помощью Python 
Следующая статьяРефакторинг кода Go для тестопригодности: возможности интерфейсов