← Back toDrag and drop in React

Swap items in a sortable list

Written byPhuoc Nguyen
Created
04 Dec, 2023
Tags
HTML 5 drag and drop, sortable list
In our previous post, we talked about creating a sortable list that lets users arrange items by dragging and dropping them into position. But what if we want to swap the item being dragged with the target item it's dropped on?
Sortable lists are crucial in e-commerce platforms, project management tools, and content management systems where prioritizing items is essential. Allowing users to swap items makes it easy for them to manage their information without having to manually input each item's new position.
Swapping items in a sortable list is particularly useful when users need to organize and prioritize data. For example, in an e-commerce platform, users can rearrange product listings to showcase popular or new products at the top. Similarly, project managers can use sortable lists to schedule tasks and adjust timelines based on priority or dependencies.
Sortable lists are also common in online survey tools where respondents can rank their preferences by dragging and dropping options. This feature allows survey creators to collect valuable feedback and analyze results based on the most preferred options.
Overall, swapping items in a sortable list is a versatile functionality that provides users with more control over their data and enhances the usability of web applications across various industries.
In this post, we'll learn how to implement this functionality with React.

Swapping a dragged item with a dropped target

In order to swap items, we'll need to modify the dragstart and dragend events that we implemented in the previous post. Let's revisit how we attach the drag event handlers to each item in the list.
tsx
items.map((item, index) => (
<div
onDragOver={(e) => handleDragOver(e, index)}
onDragEnd={(e) => handleDragEnd(e, index)}
>
{item.content}
</div>
))
The `handleDragOver` function gets called when you drag an item over a list that you can sort. It takes two arguments: an event object and an index parameter. The `index` parameter represents the index of the item that you're dragging over.
First, we prevent the default behavior of the dragover event so you can drop the item onto the target element. Then, we check if the item you're dragging is not the same as the target element. If they're not the same, we update the state of our draggable items by setting `dragOverIndex` to the index of the target element.
By updating `dragOverIndex`, we can keep track of which item is currently being dragged and which item it will be swapped with once it's dropped.
Here's how we handle the `dragover` event:
ts
const handleDragOver = (e, index) => {
e.preventDefault();
if (dragNode.current !== e.target) {
setDragOverIndex(index);
}
};
When an item is finished being dragged, it triggers the `handleDragEnd` function. This function takes an event object and an index parameter as arguments. The `index` parameter represents the index of the item that the dragged item is being dropped onto.
In this function, we first check if `dragOverIndex` is not equal to -1 and if the index is not equal to `dragOverIndex`. If both conditions are true, we know we need to swap the positions of the dragged item with the target item.
To do this, we create a new array of items by copying all items from the old array using the spread operator. Then, we get the dragged item and target item from their respective indexes in this new array. We swap their positions by assigning one to another.
Finally, we update our state with these new items by calling `setItems` with our updated list of items. This way, when React re-renders our component, it will display our sortable list with swapped items in their new positions.
Here's how we handle the `dragend` event:
ts
const handleDragEnd = (e, index) => {
if (dragOverIndex === -1 || index === dragOverIndex) {
return;
}
let newItems = [...items];
const draggingItem = newItems[dragOverIndex];
const targetItem = newItems[index];

newItems[dragOverIndex] = targetItem;
newItems[index] = draggingItem;

setItems(newItems);
};
Check out the demo below and try dragging an item and dropping it over another item to see them swap places.

Adding visual cues for item swapping

To make our user experience even better, we can add a visual cue to show users that items will be swapped when they drop an item onto another. We can do this by displaying a small animation or icon when the dragged item is hovering over a target item.
To achieve this, we can use CSS animations. We'll define a class that applies a transform animation to the target element when it's being hovered over by the dragged item. The animation can rotate or scale the target element to indicate that it will be swapped with the dragged item.
Let's look at an example of how we can define this class:
css
.highlight {
animation: scale 0.3s linear infinite alternate;
}

@keyframes scale {
from {
transform: scale(1);
}
to {
transform: scale(1.2);
}
}
In this example, we're using the `scale` class to make the target element pulsate when the dragged item hovers over it. The animation continuously scales up and down the target element, creating a cool pulsating effect.
To highlight the target item, we can check if the current item's index is equal to `overIndex`. If it is, we add the `highlight` class to this item by passing it as a `className` prop. Here's how to update the code:
tsx
items.map((item, index) => (
<div className={index === overIndex ? "highlight" : ""}>
{item.content}
</div>
))
Now, when you drag an item over another item in the list, it will be highlighted with a pulsating effect. This addition of a visual cue will help users to better understand how swapping items works in our sortable list and make them feel more confident in using this feature.
Check out the demo below to see it in action:

Conclusion

In this post, we learned how to use React to swap items in a sortable list. By modifying the `dragstart` and `dragend` events, users can now easily swap items in the list, providing more control over their data and enhancing the user experience. We also added visual cues to make the process even smoother.
Swapping items in a sortable list can significantly improve productivity and usability across various industries, including e-commerce platforms, project management tools, and content management systems. By allowing users to swap items, they can manage their information more efficiently without having to manually input each item's new position. This simple functionality can make a big difference in streamlining workflows and maximizing productivity.
If you found this post helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

Questions? 🙋

Do you have any questions about front-end development? If so, feel free to create a new issue on GitHub using the button below. I'm happy to help with any topic you'd like to learn more about, even beyond what's covered in this post.
While I have a long list of upcoming topics, I'm always eager to prioritize your questions and ideas for future content. Let's learn and grow together! Sharing knowledge is the best way to elevate ourselves 🥷.
Ask me questions

Recent posts ⚡

Newsletter 🔔

If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn