question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

sortable IDs must be strings, and this isn't documented anywhere

See original GitHub issue

Based on the documentation, it seems like the id prop used by the Sortable preset can be any primitive, including a number. However, in the examples below, only strings produce the correct, animated, result.

It unfortunately cost me several days of debugging to figure this out, as the only thing broken are the animations - the rest of the functionality, including the onDragStart/onDragEnd stuff, works as expected with numeric IDs!

It would be great if numeric IDs were supported; failing that, it would ideally be a runtime error to provide non-numeric IDs to sortable interfaces!

Works properly:

import React, { useState } from 'react'
import {
  DndContext,
  closestCenter,
  MouseSensor,
  TouchSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core'
import {
  useSortable,
  arrayMove,
  SortableContext,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'

export function MinimalDnd({ packQuery }) {
  const [items, setItems] = useState(['1', '2', '3'])
  const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor))

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        {items.map((id) => (
          <SortableItem key={id} id={id} />
        ))}
      </SortableContext>
    </DndContext>
  )

  function handleDragEnd(event) {
    const { active, over } = event

    if (active.id !== over.id) {
      setItems((items) => {
        const oldIndex = items.indexOf(active.id)
        const newIndex = items.indexOf(over.id)

        return arrayMove(items, oldIndex, newIndex)
      })
    }
  }
}

export function SortableItem(props) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: props.id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  }

  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      ID: {props.id}
    </div>
  )
}

Animations completely broken

import React, { useState } from 'react'
import {
  DndContext,
  closestCenter,
  MouseSensor,
  TouchSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core'
import {
  useSortable,
  arrayMove,
  SortableContext,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'

export function MinimalDnd({ packQuery }) {
  const [items, setItems] = useState([1, 2, 3])
  const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor))

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        {items.map((id) => (
          <SortableItem key={id} id={id} />
        ))}
      </SortableContext>
    </DndContext>
  )

  function handleDragEnd(event) {
    const { active, over } = event

    if (active.id !== over.id) {
      setItems((items) => {
        const oldIndex = items.indexOf(active.id)
        const newIndex = items.indexOf(over.id)

        return arrayMove(items, oldIndex, newIndex)
      })
    }
  }
}

export function SortableItem(props) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: props.id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  }

  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      ID: {props.id}
    </div>
  )
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
claudericcommented, Jan 26, 2022

Seems reasonable, feel free to open a new issue or submit a PR where an error is thrown in development only

1reaction
qrohlfcommented, Jan 26, 2022

I still think that my recommendation for throwing a runtime error when useSortable is passed a non-string id is a reasonable one, since this is a complex library with a lot of documentation, and the current behavior of mostly working, but with broken animations when a non-string ID is passed is extremely confusing if you overlook that doc section!

Happy to submit a PR if you think it’s a good idea.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Throw a descriptive error in development when non-string IDs are ...
I plan to add runtime checks to the useSortable and SortableContext hook that will ... sortable IDs must be strings, and this isn't...
Read more >
Automatically generating unique DOM ids? - Stack Overflow
These ids (or names) will not be mentioned explicitly anywhere else in the code, and therefore they could be any random strings, and,...
Read more >
What would you use as a sortable, globally unique, ID?
The objective is to have an ID that has the following two inherent properties: globally unique: if two different nodes generate an ID, ......
Read more >
Identity Crisis: Sequence v. UUID as Primary Key — brandur.org
Multiple entities can generate IDs independently, but still store ... all ULIDs created anywhere nicely sortable compared to each other.
Read more >
Best Practices for Comparing Strings in .NET - Microsoft Learn
But sorting or comparing strings is not always a culture-sensitive operation. ... culture-insensitive identifier, the code should instead be ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found