Skip to main content

Usage

The useSortable hook combines draggable and droppable behavior with sorting logic. Import it from @dnd-kit/solid/sortable.
Use getter syntax for reactive props to maintain Solid’s fine-grained reactivity. Without getters, the hook reads prop values once during setup and never re-runs its effects when they change.

Without the move helper

The example above uses the move helper from @dnd-kit/helpers, a convenience function that takes your items and a drag event and returns a new array with the item moved to its new position. It supports flat arrays and grouped records, handles canceled drags, and works with optimistic sorting out of the box. If you need more control over state updates, you can manage state manually using the isSortable type guard and the sortable properties (initialIndex, index). With optimistic sorting enabled (the default), you only need to handle the onDragEnd event:
import {createSignal, For} from 'solid-js';
import {DragDropProvider} from '@dnd-kit/solid';
import {useSortable, isSortable} from '@dnd-kit/solid/sortable';

function SortableItem(props) {
  const {ref} = useSortable({
    get id() { return props.id; },
    get index() { return props.index; },
  });

  return <li ref={ref} class="item">Item {props.id}</li>;
}

export default function App() {
  const [items, setItems] = createSignal([1, 2, 3, 4]);

  return (
    <DragDropProvider
      onDragEnd={(event) => {
        if (event.canceled) return;

        const {source} = event.operation;

        if (isSortable(source)) {
          const {initialIndex, index} = source;

          if (initialIndex !== index) {
            setItems((items) => {
              const newItems = [...items];
              const [removed] = newItems.splice(initialIndex, 1);
              newItems.splice(index, 0, removed);
              return newItems;
            });
          }
        }
      }}
    >
      <ul class="list">
        <For each={items()}>
          {(id, index) => <SortableItem id={id} index={index()} />}
        </For>
      </ul>
    </DragDropProvider>
  );
}
You can call event.preventDefault() in an onDragOver handler to prevent the OptimisticSortingPlugin from optimistically updating for that specific event. This is useful when you want to conditionally block certain moves.
Learn more about optimistic sorting, type guards, and manual state management in the Sortable concepts page.

Input

id
UniqueIdentifier
required
A unique identifier. Use get id() { return props.id } for reactive values.
index
number
required
The current index in the sorted list. Use get index() { return props.index } for reactive values.
group
string
The group this sortable belongs to. Used for sorting across multiple lists.
handle
Element
A handle element. Use the handleRef callback to set it.
accept
string | string[]
The types of draggable elements this sortable accepts.
type
string
The type of this sortable element.
plugins
PluginDescriptor[]
An array of plugin descriptors for per-entity plugin configuration. Use Plugin.configure() to create descriptors. For example, Feedback.configure({ feedback: 'clone' }).
transition
SortableTransition
Animation transition configuration.
modifiers
Modifier[]
Modifiers to apply to this sortable instance.
sensors
Sensor[]
Sensors to use for this sortable instance.
collisionDetector
CollisionDetector
A custom collision detection algorithm.
collisionPriority
number
The collision priority of this sortable element. Higher values take precedence when multiple droppable elements overlap.
disabled
boolean
Whether the sortable is disabled.
data
Data
Custom data to attach to this sortable instance.

Output

ref
(element: Element) => void
A callback ref to attach to the sortable element.
handleRef
(element: Element) => void
A callback ref for a drag handle.
sourceRef
(element: Element) => void
A callback ref for the drag source element.
targetRef
(element: Element) => void
A callback ref for the drop target element.
isDragging
() => boolean
Whether this element is currently being dragged. Call as isDragging() in JSX.
isDropping
() => boolean
Whether this element is in the process of being dropped. Call as isDropping() in JSX.
isDragSource
() => boolean
Whether this element is the source of the current drag operation. Call as isDragSource() in JSX.
isDropTarget
() => boolean
Whether this element is currently a drop target. Call as isDropTarget() in JSX.
sortable
Sortable
The underlying Sortable instance.