https://github.com/harrel56/use-sortablejs
SortableJS ported to React hooks
https://github.com/harrel56/use-sortablejs
drag drag-and-drop react sortablejs
Last synced: 10 months ago
JSON representation
SortableJS ported to React hooks
- Host: GitHub
- URL: https://github.com/harrel56/use-sortablejs
- Owner: harrel56
- License: mit
- Created: 2022-08-04T19:43:36.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-04-09T19:01:50.000Z (10 months ago)
- Last Synced: 2025-04-09T20:21:01.508Z (10 months ago)
- Topics: drag, drag-and-drop, react, sortablejs
- Language: TypeScript
- Homepage: https://harrel56.github.io/use-sortablejs/
- Size: 633 KB
- Stars: 6
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# use-sortablejs
[SortableJS](https://github.com/SortableJS/Sortable) ported to React hooks.
Demo: https://harrel56.github.io/use-sortablejs
[](https://github.com/harrel56/use-sortablejs/actions/workflows/build.yml)
[](https://www.npmjs.com/package/use-sortablejs)
[](https://github.com/harrel56/use-sortablejs/blob/master/LICENSE)
[](https://www.npmjs.com/package/use-sortablejs)
[](https://bundlephobia.com/package/use-sortablejs)
[](https://bundlephobia.com/package/use-sortablejs)
Created to serve as a refreshed alternative to [react-sortablejs](https://github.com/SortableJS/react-sortablejs),
with hook design inspired by [@mui/base](https://www.npmjs.com/package/@mui/base).
## Installation
Currently, package is only available as ES module.
```sh
npm i use-sortablejs
```
Contains no external dependencies, only peer dependencies:
+ `react`: `^17.0.0 || ^18.0.0`
+ `sortablejs`: `^1.0.0`
+ `@types/react`: `^17.0.0 || ^18.0.0`
+ `@types/sortablejs`: `^1.0.0`
Package exports:
+ `SortableProvider`: sortable context provider,
+ `useSortable`: main hook which requires access to sortable context
+ and typescript definitions.
Supports:
+ all basic functionalities from `SortableJS`,
+ swap plugin (you have to mount it yourself)
+ and multidrag plugin (you have to mount it yourself).
## Usage
Before using `useSortable` hook, it's required to wrap your application with `SortableProvider`.
Preferably, there should be only one `SortableProvider` per whole application, but it's not mandatory.
Nevertheless, interactions between two sortables in separate contexts have undefined behaviour.
Example:
```tsx
// App.tsx
import {SortableProvider} from 'use-sortablejs'
import List from './List'
const App = () => {
return (
)
}
```
```tsx
// List.tsx
import {useState} from 'react'
import {useSortable} from 'use-sortablejs'
const List = () => {
const [items, setItems] = useState([
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5'
])
const {getRootProps, getItemProps} = useSortable({setItems, options: {animation: 150}})
return (
{items.map(item => {item})}
)
}
```
Where item type can be possibly anything (primitive, object of any shape, function).
## Details
All types definitions can be found in this [file](https://github.com/harrel56/use-sortablejs/blob/master/src/types.ts).
`useSortable` takes `UseSortableProps` parameter, which is an object containing:
1. `setItems`: `Dispatch>`, where `T` is your item type. In most cases this should be a `setState` function returned from React `useState` hook.
2. `options`: `ExtendedOptions`, options object which you would normally pass to `Sortable.create()`.
3. *(optional)* `cloneItem`: `(item: T) => T`, clone function to perform when item is being cloned. Defaults to internal shallow clone function.
4. *(optional)* `sortableRef`: `LegacyRef`, ref object or ref callback, which will be set/called with created `Sortable` object - set to `null` on dismount.
Additionally, all event functions that you pass to `options` object will have access to extended event object (`SortableEventExtended`),
which contains additional field `stateItem`, which corresponds to dragged item state and is directly mapped from `item` field.
### Using `sortableRef`
Leveraging `options` reactivity is the preferred way of achieving dynamic changes to `Sortable` object, but if you need more control `sortableRef` is the way to go.
```ts
const myRef = useRef(null)
const {getRootProps, getItemProps} = useSortable({setItems, sortableRef: myRef})
```
```ts
const myCallbackRef = (sortable: Sortable | null) => {
sortable?.option('sort', false)
}
const {getRootProps, getItemProps} = useSortable({setItems, sortableRef: myCallbackRef})
```
## Constraints
1. Each direct child of node with `getRootProps()` should have set props from `getItemProps(item)`.
2. Each direct child of node with `getRootProps()` should contain unique `key` prop (**NOT** list index).
3. `setItems` function should cause rerender of sortable list to reflect items state.
Behaviour is undefined if any of these constraints is not met.