MUI (Material-UI) предоставляет широкий набор компонентов для
построения интерфейсов, включая списки (List) и элементы
списка (ListItem). Взаимодействие через drag and drop в
таких списках часто требует интеграции с внешними библиотеками,
поскольку MUI не содержит встроенной поддержки drag and drop. Наиболее
популярные подходы используют библиотеку React DnD или
react-beautiful-dnd. Рассмотрим организацию drag and
drop на примере react-beautiful-dnd.
Для реализации drag and drop потребуется установить библиотеку:
npm install @mui/material @emotion/react @emotion/styled react-beautiful-dnd
@mui/material и @emotion/* необходимы для
работы MUI, а react-beautiful-dnd отвечает за функционал
перетаскивания.
Основные компоненты для drag and drop:
DragDropContext – оборачивает область,
где будет происходить перетаскивание.Droppable – контейнер, в который можно
перемещать элементы.Draggable – элемент, который можно
перемещать.Пример базовой структуры:
import React, { useState } from 'react';
import { List, ListItem, ListItemText, Paper } from '@mui/material';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
const initialItems = [
{ id: '1', text: 'Элемент 1' },
{ id: '2', text: 'Элемент 2' },
{ id: '3', text: 'Элемент 3' },
];
function DraggableList() {
const [items, setItems] = useState(initialItems);
const handleOnDragEnd = (result) => {
if (!result.destination) return;
const reorderedItems = Array.from(items);
const [removed] = reorderedItems.splice(result.source.index, 1);
reorderedItems.splice(result.destination.index, 0, removed);
setItems(reorderedItems);
};
return (
<DragDropContext onDrag End={handleOnDragEnd}>
<Droppable droppableId="droppable-list">
{(provided) => (
<List
component={Paper}
{...provided.droppableProps}
ref={provided.innerRef}
>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => (
<ListItem
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
sx={{
backgroundColor: snapshot.isDragging ? 'grey.300' : 'background.paper',
mb: 1,
}}
>
<ListItemText primary={item.text} />
</ListItem>
)}
</Draggable>
))}
{provided.placeholder}
</List>
)}
</Droppable>
</DragDropContext>
);
}
export default DraggableList;
handleOnDragEnd – функция, вызываемая
после завершения перетаскивания. Именно здесь обновляется состояние
списка.provided.placeholder – важный элемент,
который сохраняет пространство для перетаскиваемого элемента,
предотвращая визуальные «скачки» при перемещении.snapshot.isDragging – состояние
перетаскиваемого элемента. Можно использовать для динамического
изменения стиля элемента при drag.Использование sx пропсов MUI позволяет легко менять фон,
тени и другие свойства элементов во время drag:
sx={{
backgroundColor: snapshot.isDragging ? 'grey.300' : 'background.paper',
boxShadow: snapshot.isDragging ? 3 : 0,
mb: 1,
}}
Эти параметры повышают визуальную читаемость интерфейса и дают пользователю ясное понимание, какой элемент в данный момент перемещается.
Для реализации нескольких списков, между которыми можно перетаскивать
элементы, используется несколько Droppable:
<Droppable droppableId="list-1">
{...}
</Droppable>
<Droppable droppableId="list-2">
{...}
</Droppable>
При обработке onDragEnd проверяется
source.droppableId и destination.droppableId
для определения, перемещается ли элемент внутри одного списка или между
разными списками.
React.memo для ListItem.Draggable и
Droppable, лучше использовать заранее определённые функции
или методы.react-window совместно с drag and drop, чтобы улучшить
производительность.react-beautiful-dnd автоматически поддерживает прокрутку
контейнера при перемещении элемента к краю.Эта методика позволяет создавать гибкие и наглядные интерфейсы списков с drag and drop в MUI, обеспечивая высокую визуальную читаемость и удобство использования.