dnd-kit icon indicating copy to clipboard operation
dnd-kit copied to clipboard

[experimental] Add documentation for getting reordered state using `move` in `useSortable` doc

Open sazid opened this issue 6 months ago • 3 comments

Added the following example to the docs for the experimental version:

import { move } from '@dnd-kit/helpers';

function SortableDemo() {
  const [items, setItems] = useState([1, 2, 3, 4]);

  useEffect(() => {
    console.log(items); // print out the reordered array 
  }, [items]);

  return (
    <DragDropProvider onDragEnd={(event) => setItems(move(items, event))}>
      <ul>
        {items.map((id, index) => (
          <Sortable key={id} id={id} index={index} />
        ))}
      </ul>
    </DragDropProvider>
  );
}

sazid avatar Jun 24 '25 19:06 sazid

⚠️ No Changeset found

Latest commit: 5d78c811f72e92b42067e54da11139513ab7292b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Jun 24 '25 19:06 changeset-bot[bot]

I don't recommend this being added in with the way move currently functions. There is some very confusing behavior in there, largely from the following:

const findIndex = (item: Items[0], id: UniqueIdentifier) =>
  item === id || (typeof item === 'object' && 'id' in item && item.id === id);

This completely ignores the id that's passed into the useSortable hook, instead relying on the existence of an id field within the item, which in turn breaks the ability to sort the controlled list when using any sort of computed id or a data structure with an unconventional natural id. There's also the issue of the optimistic update obfuscating the successful drag operation, since both source and target fields end up with the same id. I think the only current workaround is to use the initialIndex and index fields present on the sortable field within both the operation source and target. These aren't present on the provided types but it works.

rrmahalo avatar Sep 11 '25 18:09 rrmahalo

or, convert it to sortable id before move then convert it back after:

		const sortableIds = ids.map(id => makeSortableId(id))
		const nextSortableIds = move(sortableIds, event)
		const nextIds = nextSortableIds.map(id => unwrapSortableId(id))
		persist(nextIds)
		useSortable({ id: makeSortableId(id) })

songkeys avatar Nov 14 '25 15:11 songkeys