Build React Drag N Drop With Dnd Kit
Build React Drag N Drop With Dnd Kit

In this post you will learn how to implement drag and drop inside React.

The main problem with drag n drop is that it takes quite a lot of effort to implement it without library. This is why I highly recommend you to pick good library for this.

What library to pick?

But here is the problem. If you google "react drag n drop" the top result are libraries which are either abandoned or the API for them is really strange or not comfortable. For example react-beautiful-dnd is not maintained and react-dnd which works is not that comfortable to use.

This is why what I recommend you is dnd-kit. It is a good modern library with comfortable API.

Dnd kit website

Here we have lots of stuff like Droppable, Draggable, different sensors (also for touch devices) and also Sortable.

The whole library is built with hooks, this is exactly what we want.

Adding Dnd Kit

The goal of this video to implement this is with sorting based on the drag n drop.

Result

Here we have a list of users and a possibility to add new user to the list. We just need to attach drag and drop to sort this list.

Let's install all needed dependencies.

npm i@dnd-kit/core @dnd-kit/utilities @dnd-kit/sortable

This is what we need to implement sort. If you just need drag and drop you don't need sortable.

<DndContext collisionDetection={closestCenter} onDragEnd={onDragEnd}>
  {users.map((user) => (
    <div key={user.id} className="user">{user.name}</div>
  ))}
</DndContext>

Here we wrapped our list of users with DndContext. It's a container where we can drag and drop. Inside we provide collisionDetection which defines how element will react and onDragEnd callback which we need to implement.

<DndContext collisionDetection={closestCenter} onDragEnd={onDragEnd}>
  <SortableContext items={users} strategy={verticalListSortingStrategy}>
    {users.map((user) => (
      <div key={user.id} className="user">{user.name}</div>
    ))}
  </SortableContext>
</DndContext>

Now we added SortableContext which is used for sorting the list. We set verticalListSortingStrategy inside as our list goes in vertical direction.

Adding useSortable

We also need to move every single element in additional component because for each element we must call a hook inside.

const SortableUser = ({ user }) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({ id: user.id });
  const style = {
    transition,
    transform: CSS.Transform.toString(transform),
  };

  return (
    <div
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      className="user"
    >
      {user.name}
    </div>
  );
};

Here is our additional component. We used useSortable where we provided unique ID. We also attached lots of styles, attributes and listeners from this library to every element.

<DndContext collisionDetection={closestCenter} onDragEnd={onDragEnd}>
  <SortableContext items={users} strategy={verticalListSortingStrategy}>
    {users.map((user) => (
      <SortableUser key={user.id} user={user} />
    ))}
  </SortableContext>
</DndContext>

This is how our markup look now.

Sorting an array

Our last step is to implement onDragEnd callback and resort the list based on dragged element.

const onDragEnd = (event) => {
  const { active, over } = event;
  if (active.id === over.id) {
    return;
  }
  setUsers((users) => {
    const oldIndex = users.findIndex((user) => user.id === active.id);
    const newIndex = users.findIndex((user) => user.id === over.id);
    return arrayMove(users, oldIndex, newIndex);
  });
};

Here we get an event from dnd kit with all information about what we dragged and at what position. To sort our array and switch positions we use a helper from this library which is called arrayMove. It returns a new array with switched position.

Result

As you can see in browser our drag n drop is fully working.

And actually if you are interested to learn how to build real React project from start to the end make sure to check my React hooks course.

📚 Source code of what we've done