SortableJS — это мощная библиотека для создания интерактивных списков
с перетаскиванием элементов. Для работы в React рекомендуется
использовать официальный обёртку react-sortablejs, которая
обеспечивает удобное связывание состояния компонентов с действиями
пользователя.
Установка через npm:
npm install sortablejs react-sortablejs
Подключение в компоненте:
import React, { useState } from 'react';
import Sortable from 'react-sortablejs';
SortableJS работает на основе DOM-элементов, поэтому при интеграции с
React ключевым моментом является синхронизация состояния
компонента с порядком элементов в списке. Это достигается
хранением массива элементов в useState и обновлением его
при событии onChange.
Пример базового списка:
const App = () => {
const [items, setItems] = useState(['Элемент 1', 'Элемент 2', 'Элемент 3']);
return (
<Sortable
tag="ul"
onCha nge={(order, sortable, evt) => setItems(order)}
>
{items.map(item => (
<li key={item}>{item}</li>
))}
</Sortable>
);
};
Особенности этого подхода:
tag задаёт HTML-тег контейнера.onChange получает новый порядок элементов в виде
массива.key.SortableJS поддерживает множество опций, позволяющих управлять поведением списка:
animation — скорость анимации при перемещении
элементов.group — позволяет объединять несколько списков для
перетаскивания между ними.disabled — отключает сортировку.handle — задаёт селектор для перетаскиваемой
области.ghostClass — класс, применяемый к элементу во время
перетаскивания.Пример с опциями:
<Sortable
tag="ul"
animation={150}
handle=".drag-handle"
ghostClass="dragging"
onCha nge={(order) => setItems(order)}
>
{items.map(item => (
<li key={item}>
<span className="drag-handle">☰</span> {item}
</li>
))}
</Sortable>
С помощью опции group можно создавать взаимодействующие
списки, позволяя перемещать элементы между ними.
const [listA, setListA] = useState(['A1', 'A2', 'A3']);
const [listB, setListB] = useState(['B1', 'B2', 'B3']);
<Sortable
tag="ul"
group="shared"
onCha nge={setListA}
>
{listA.map(item => <li key={item}>{item}</li>)}
</Sortable>
<Sortable
tag="ul"
group="shared"
onCha nge={setListB}
>
{listB.map(item => <li key={item}>{item}</li>)}
</Sortable>
Ключевой момент — одинаковое имя группы для взаимодействующих списков. При перемещении элемент автоматически удаляется из одного массива и добавляется в другой.
SortableJS может работать не только с простыми строками, но и с
компонентами React с собственными состояниями. Для корректной работы
нужно использовать уникальные идентификаторы в
key, а порядок элементов хранить в состоянии.
const tasks = [
{ id: 1, text: 'Сделать задачу 1' },
{ id: 2, text: 'Сделать задачу 2' }
];
const [taskList, setTaskList] = useState(tasks);
<Sortable
tag="ul"
onCha nge={(order, sortable) => {
const sortedTasks = order.map(id => taskList.find(task => task.id.toString() === id));
setTaskList(sortedTasks);
}}
>
{taskList.map(task => (
<li key={task.id}>{task.text}</li>
))}
</Sortable>
SortableJS предоставляет множество событий для тонкой настройки взаимодействия:
onStart — начало перетаскивания.onEnd — завершение перетаскивания.onAdd — элемент добавлен из другого списка.onRemove — элемент удалён в другой список.onSort — порядок элементов изменён.Пример логирования событий:
<Sortable
tag="ul"
onSt art={() => console.log('Перетаскивание начато')}
on End={() => console.log('Перетаскивание завершено')}
on Add={(evt) => console.log('Добавлен элемент', evt.item)}
onRem ove={(evt) => console.log('Удалён элемент', evt.item)}
>
{taskList.map(task => <li key={task.id}>{task.text}</li>)}
</Sortable>
SortableJS легко интегрируется с формами, сохраняя порядок элементов при отправке данных. Можно хранить массив идентификаторов и отправлять его на сервер.
const handleSubmit = () => {
const order = taskList.map(task => task.id);
fetch('/save-order', {
method: 'POST',
body: JSON.stringify({ order }),
headers: { 'Content-Type': 'application/json' }
});
};
React.memo для элементов списка с большим
количеством данных.setState через
onChange — можно применять debounce.Можно динамически включать или отключать сортировку через
disabled:
const [sortableEnabled, setSortableEnabled] = useState(true);
<Sortable
tag="ul"
disabled={!sortableEnabled}
>
{items.map(item => <li key={item}>{item}</li>)}
</Sortable>
Переключение состояния позволяет создавать интерактивные интерфейсы с включаемой и выключаемой сортировкой.
SortableJS поддерживает кастомизацию через CSS-классы:
.sortable-ghost — элемент-призрак при
перетаскивании..sortable-chosen — выбранный элемент..sortable-drag — элемент, который перемещается в данный
момент.Пример CSS:
.dragging {
opacity: 0.5;
background-color: #f0f0f0;
}
.drag-handle {
cursor: grab;
}
Анимация задаётся опцией animation в миллисекундах, что
обеспечивает плавное перемещение элементов.
SortableJS в сочетании с React обеспечивает гибкую и мощную платформу для создания интерактивных списков, позволяя интегрировать перетаскивание с состоянием приложения, несколькими списками и кастомными компонентами. Правильная работа с ключами, состоянием и событиями делает взаимодействие пользователя плавным и предсказуемым.