React SortableJS Bindings
react-sortablejs provides idiomatic React bindings for the powerful SortableJS drag-and-drop library, enabling developers to create interactive, sortable lists with declarative React components. It abstracts away direct DOM manipulation, integrating smoothly with React's state management. The package is currently at version 6.1.4 and receives maintenance updates focusing on bug fixes and dependency updates, though the README indicates it's "not considered ready for production". It differentiates itself by offering a ReactSortable component that directly accepts SortableJS options as props, along with supporting both functional and class-based React components and providing clear mechanisms for integrating SortableJS plugins like MultiDrag and Swap.
Common errors
-
SortableJS: MultiDrag and Swap are not available in this version. You must mount the plugin with sortable ONCE ONLY.
cause Attempting to use a SortableJS plugin (e.g., via `multiDrag` or `swap` props on `<ReactSortable>`) without globally mounting its constructor via `Sortable.mount()`.fixCall `Sortable.mount(new MultiDrag(), new Swap());` (or the relevant plugin constructors) once in your application's entry point before `<ReactSortable />` is rendered. -
TypeError: (0 , react_sortablejs__WEBPACK_IMPORTED_MODULE_2__.Sortable) is not a constructor
cause Incorrectly trying to instantiate `Sortable` directly (e.g., `new Sortable()`). The `Sortable` export from `react-sortablejs` is a static class for mounting plugins, not for direct instantiation.fixUse `Sortable.mount(new PluginConstructor())` for plugins. The core `SortableJS` instance is managed internally by `ReactSortable`.
Warnings
- gotcha The library is explicitly stated as 'not considered ready for production' in its README. While actively maintained, users should exercise caution.
- gotcha SortableJS plugins (e.g., MultiDrag, Swap) must be explicitly mounted globally via `Sortable.mount(new PluginConstructor())` before being enabled as props on `<ReactSortable />`.
- gotcha When updating the `list` prop using the `setList` callback, ensure you provide a new array reference for React to detect changes and trigger a re-render. Direct mutation of the array will not work.
- breaking Older versions might have compatibility issues with React 18, particularly regarding missing `children` prop types.
Install
-
npm install react-sortablejs -
yarn add react-sortablejs -
pnpm add react-sortablejs
Imports
- ReactSortable
import ReactSortable from 'react-sortablejs'; // No default export const ReactSortable = require('react-sortablejs').ReactSortable; // CommonJS (library is ESM-first)import { ReactSortable } from 'react-sortablejs'; - Sortable
import * as Sortable from 'react-sortablejs'; // Sortable is not the default export const { Sortable } = require('react-sortablejs'); // CommonJSimport { Sortable } from 'react-sortablejs'; - MultiDrag
const MultiDrag = require('react-sortablejs').MultiDrag; // CommonJSimport { MultiDrag } from 'react-sortablejs';
Quickstart
import React, { FC, useState } from "react";
import { ReactSortable } from "react-sortablejs";
interface ItemType {
id: number;
name: string;
}
export const BasicFunction: FC = () => {
const [state, setState] = useState<ItemType[]>([
{ id: 1, name: "shrek" },
{ id: 2, name: "fiona" },
{ id: 3, name: "donkey" },
]);
return (
<div style={{ maxWidth: '300px', margin: '20px auto', border: '1px solid #eee', padding: '10px' }}>
<h3>Drag and Drop List</h3>
<ReactSortable list={state} setList={setState} animation={150} group="shared-group">
{state.map((item) => (
<div
key={item.id}
style={{
padding: '10px',
margin: '5px 0',
border: '1px solid #ccc',
backgroundColor: '#f9f9f9',
cursor: 'grab'
}}
>
{item.name}
</div>
))}
</ReactSortable>
</div>
);
};