Drag and Drop Feature in any application can provide a rich user experience. There are a number of libraries that can provide this feature, for example,
- React DnD
- React-beautiful-dnd
- SortableJs
But, due to certain limitations in each library, one cannot have full access to customize things. However, building this feature from scratch can help us add more flexibility to the functioning. Our main focus in this blog is to build a drag-and-drop feature from scratch without any library and to minimize the rendering to increase the performance of the application.
Setting up the Project
Let’s start by creating a new project in react. You can use create-react-app to set up the project.
npx create-react-app drag-and-drop-demo
Creating the Component
const DragAndDropContainer = () => {
Const[(items, setItems)] = useState([/ * Array of draggable items * /]);
return (
<div className='drag-and-drop-container'>
{items?.map((item, index) => (
<div
key={item?.id}
draggable
onDragStart={onDragStart(item)}
onDragEnd={onDrop}
className='draggable-item'
onDragOver={onDragOver}
>
{item}
</div>
))}
</div>
);
};
Implementing the Drag and Drop Functionality
Here is the core part of this feature. By starting the dragging, the event handlers will handle the event and store the item’s ID in a state.
const [dragedItem, setDraggedItem] = useState(null);
const onDragStart = (item) => (event) => {
event.preventDefault();
setDraggedItem(item.id);
As the draggable item is stored in a state, we have to highlight the drag-over container. For this, we can use two different event handlers:
- onDragOver
- onDragEnter
These two event handlers may provide us with the ID of drag-over items. We are going to implement this through the onDragOver event handler.
const [dragOverContainer, setDragOverContainer] = useState(null);
const outSideContainerRef = useRef(null);
const onDragOver = (item) => (event) => {
event.preventDefault();
if (item.id == dragOverContainer) {
outSideContainerRef.current = false;
} else {
setDragOverContainer(item.id);
outSideContainerRef.current = false;
}
};
In the above function, we are checking whether a draggable item is dragging over the same container repeatedly. In this way, we will prevent the unnecessary re-rendering. Also, outside container ref can be seen being used. It’s being used to prevent the final action. If the user drops the draggable item outside the dragover container, then we have to handle the scenario, so we will use another event handler on onDragLeave, in that case.
const onDragLeave = (event) => {
event.preventDefault();
outSideContainerRef.current = true;
};
Now, the last step is to perform the action of dropping draggable item(s).
const onDrop = (event) => {
event.preventDefault();
if (outSideContainerRef.current == true) return;
else {
// perform action on dropping of item
}
};
The above function is going to handle the drop of items. It will also handle the drop outside the drag-over container.
Styling and Feedback
To make this feature visually more appealing, one can use CSS styles for the draggable items and the container. visual feedback can also be implemented by changing the appearance of the dragged item while being dragged.
Conclusion
In this article, we focused on implementing the custom drag-and-drop feature in React without using any external library. We’ve also highlighted the importance of minimizing the rendering to improve the performance. By understanding the core concepts and optimizing the components, one can create a smooth and efficient drag-and-drop experience.