# react-easy-sort

> A React component to sort items in lists or grids

Latest version **1.8.0** (published 2025-10-08) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-easy-sort
pnpm add react-easy-sort
yarn add react-easy-sort
bun add react-easy-sort
```

## Health

**Score 35/100 (D)** — status: maintenance-mode.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.8.0 |
| Published | 2025-10-08 |
| First published | 2021-02-05 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=18 |
| Dependencies | 1 |
| Unpacked size | 408.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 197 |
| Author | Valentin Hervieu |
| Maintainers | valentinhervieu |
| Keywords | react, sort, sortable, sortable grid, sortable list |

## Links

- npm: https://www.npmjs.com/package/react-easy-sort
- Repository: https://github.com/ValentinH/react-easy-sort
- Homepage: https://ValentinH.github.io/react-easy-sort/
- Issues: https://github.com/ValentinH/react-easy-sort/issues
- npm.io page: https://npm.io/package/react-easy-sort

## Dependencies (1)

- [tslib](https://npm.io/package/tslib.md) ^2.8.1

## Alternatives

- [@lexical/table](https://npm.io/package/@lexical/table.md) — 3.0M weekly downloads
- [mantine-datatable](https://npm.io/package/mantine-datatable.md) — 98.2K weekly downloads
- [react-native-collapsible-tab-view](https://npm.io/package/react-native-collapsible-tab-view.md) — 70.6K weekly downloads
- [@handsontable/vue3](https://npm.io/package/@handsontable/vue3.md) — 16.1K weekly downloads
- [vuewordcloud](https://npm.io/package/vuewordcloud.md) — 7.2K weekly downloads

## Recent versions

- 1.8.0 (latest) — 2025-10-08
- 1.7.0 — 2025-09-04
- 1.6.0 — 2023-10-18
- 1.5.3 — 2023-09-25
- 1.5.2 — 2023-09-06
- 1.5.1 — 2022-11-10
- 1.5.0 — 2022-05-20
- 1.4.1 — 2022-02-18
- 1.4.0 — 2022-02-13
- 1.3.3 — 2021-11-05
- 1.3.2 — 2021-09-29
- 1.3.1 — 2021-08-11
- 1.3.0 — 2021-08-11
- 1.2.0 — 2021-07-01
- 1.1.0 — 2021-06-29
- … 8 more at https://npm.io/package/react-easy-sort/versions

## README

# react-easy-sort

A React component to sort items in lists or grids

[![version][version-badge]][package] [![Monthly downloads][npmstats-badge]][npmstats] ![gzip size][brotli-badge] [![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs]

![react-easy-sort-demo](https://user-images.githubusercontent.com/2678610/107036435-f27fbb00-67b9-11eb-8e3f-72a000586d35.gif)

The goal of this component is to allow sorting elements with drag and drop.

It is mobile friendly by default. It doesn't block scrolling the page when swiping inside it:
the user needs to press an item during at least 200ms to start the drag gesture.

On non-touch devices, the drag gesture only starts after moving an element by at least one pixel.
This is done to avoid blocking clicks on clickable elements inside an item.

## Features

- Supports horizontal and vertical lists
- Supports grid layouts
- Mobile-friendly
- IE11 support 🙈

## Demo

Check out the examples:

- [Example with grid layout](https://codesandbox.io/s/react-easy-sort-grid-demo-87ev9)
- [Example with vertical list layout](https://codesandbox.io/s/react-easy-sort-vertical-list-demo-njg4i)
- [Example with horizontal list layout](https://codesandbox.io/s/react-easy-sort-horizontal-list-demo-69b3k)
- [Interactive avatars demo](https://codesandbox.io/s/react-easy-sort-images-demo-486qk)
- [Example with custom knobs](https://codesandbox.io/s/react-easy-sort-custom-knob-demo-ij37h)

## Installation

```shell
yarn add react-easy-sort
```

or

```shell
npm install react-easy-sort --save
```

## Basic usage

```js
import SortableList, { SortableItem } from 'react-easy-sort'
import { arrayMoveImmutable } from 'array-move'

const App = () => {
  const [items, setItems] = React.useState(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'])

  const onSortEnd = (oldIndex: number, newIndex: number) => {
    setItems((array) => arrayMoveImmutable(array, oldIndex, newIndex))
  }

  return (
    <SortableList onSortEnd={onSortEnd} className="list" draggedItemClassName="dragged">
      {items.map((item) => (
        <SortableItem key={item}>
          <div className="item">{item}</div>
        </SortableItem>
      ))}
    </SortableList>
  )
}
```

## Props

### SortableList

| Name                     |                                   Description                                   |                      Type                      |         Default |
|--------------------------|:-------------------------------------------------------------------------------:|:----------------------------------------------:|----------------:|
| **as**                   |                  Determines html tag for the container element                  |         `keyof JSX.IntrinsicElements`          |           `div` |
| **onSortStart**          |                  Called when the user starts a sorting gesture                  |                  `() => void`                  |               - |
| **onSortMove**           |     Called when the dragged item changes position during a sorting gesture      |          `(newIndex: number) => void`          |               - |
| **onSortEnd\***          |                Called when the user finishes a sorting gesture.                 | `(oldIndex: number, newIndex: number) => void` |               - |
| **draggedItemClassName** |                     Class applied to the item being dragged                     |                    `string`                    |               - |
| **lockAxis**             |                     Determines if an axis should be locked                      |                 `'x'` or `'y'`                 |                 |
| **allowDrag**            |                     Determines whether items can be dragged                     |                   `boolean`                    |          `true` |
| **customHolderRef**      |          Ref of an element to use as a container for the dragged item           |     `React.RefObject<HTMLElement \| null>`     | `document.body` |
| **dropTarget**           |                      React element to use as a dropTarget                       |                  `ReactNode`                   |                 |
| **autoScroll**           | Determines whether the containing element (or window) should scroll during sort |                   `boolean`                    |         `false` |

### SortableItem

This component doesn't take any other props than its child. This child should be a single React element that can receives a ref. If you pass a component as a child, it needs to be wrapped with `React.forwardRef()`.

### SortableKnob

You can use this component if you don't want the whole item to be draggable but only a specific area of it.

```js
import SortableList, { SortableItem, SortableKnob } from 'react-easy-sort'
import arrayMove from 'array-move'

const App = () => {
  const [items, setItems] = React.useState(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'])

  const onSortEnd = (oldIndex: number, newIndex: number) => {
    setItems((array) => arrayMove(array, oldIndex, newIndex))
  }

  return (
    <SortableList onSortEnd={onSortEnd} className="list" draggedItemClassName="dragged">
      {items.map((item) => (
        <SortableItem key={item}>
          <div className="item">
            <SortableKnob>
              <div>Drag me</div>
            </SortableKnob>
            {item}
          </div>
        </SortableItem>
      ))}
    </SortableList>
  )
}
```

This component doesn't take any other props than its child. This child should be a single React element that can receive a ref. If you pass a component as a child, it needs to be wrapped with `React.forwardRef()`.

## Recommended CSS rules

To disable browser default behaviors that can interfer with the dragging experience, we recommend adding the following declarations on the "items":

- `user-select: none;`: disable the selection of content inside the item (the blue box)
- `pointer-events: none;`: required for some browsers if your items contain images (see the [Interactive avatars demo](https://codesandbox.io/s/react-easy-sort-images-demo-486qk))

## Development

```shell
yarn
yarn start
```

Now, open `http://localhost:3001/index.html` and start hacking!

## License

[MIT](https://github.com/ValentinH/react-easy-sort/blob/master/LICENSE)

## Maintainers

This project is maintained by Valentin Hervieu.

This project was originally part of [@ricardo-ch](https://github.com/ricardo-ch/) organisation because I (Valentin) was working at Ricardo.
After leaving this company, they gracefully accepted to transfer the project to me. ❤️

## Alternatives

- https://github.com/clauderic/react-sortable-hoc : before creating this library, I was using it and it was also supporting grid layouts. However, we had a lot of errors reported to our Sentry and this project was not maintained anymore.
- https://github.com/atlassian/react-beautiful-dnd: another great library for sorting items. However, it doesn't support grid layouts (as of 2021-02-05).

[npm]: https://www.npmjs.com/
[node]: https://nodejs.org
[version-badge]: https://img.shields.io/npm/v/react-easy-sort.svg?style=flat-square
[package]: https://www.npmjs.com/package/react-easy-sort
[downloads-badge]: https://img.shields.io/npm/dm/react-easy-sort.svg?style=flat-square
[npmstats]: https://npm-stat.com/charts.html?package=react-easy-sort&from=2021-02-01
[npmstats-badge]: https://img.shields.io/npm/dm/react-easy-sort.svg?style=flat-square
[brotli-badge]: http://img.badgesize.io/https://unpkg.com/react-easy-sort/umd/react-easy-sort.min.js?compression=brotli&style=flat-square&1
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
[license]: https://github.com/ValentinH/react-easy-sort/blob/main/LICENSE
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com

---
_Source: https://npm.io/package/react-easy-sort · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
