This tutorial is to help create a drag-and-drop feature with a React component. This component renders a view with a draggable element on a drop area.
The drag and drop feature is a modern and attractive way of allowing users to interact. It allows inline editing of order, status or position of a website component. If you want to see how to create a form builder with the drop and drop feature, the linked Laravel article has the code.
This example will help you to learn, how to enable the drag and drop feature to an element using React. We have already seen many examples of drag and drop using the jQuery library.
View demo
This React script sets an HTML boundary to drag an element. This applies the drag-and-drop feature to an image element returned by the React component.
It is a two-step process for creating a React drag and drop. The below list includes one more preliminary step for beginners.
The below steps give a structural App where the drag-and-drop code has to be added.
npm install -g create-react-app
to get the App structure.npx create-react-app react-drag-and-drop
.cd react-drag-and-drop
.npm start
to run the React component on a DEV.Previously, I added the steps to create a new React app when creating a React select box code. The below list gives the list again for the readers who are directly landing in this article.
The following section gives the code to enable the created React App with a drag-and-drop feature.
This JSX code contains an outer drop area with a draggable image element. The below script sets the React logo to the draggable element.
The drop area has an attribute to invoke the hover and drop events during the drag and drop. The image draggable invokes the registered JS when starts dragging.
src/App.js (JSX)
import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
const [image, setImage] = useState({ logo_path: logo });
...
...
return (
<div className="App">
<h1>React Drag and Drop</h1>
<div
className="drop-area"
onDragOver={(event) => handleDragOver(event)}
onDrop={(event) => handleDrop(event)}
>
<img
src={image.logo_path}
alt="Logo"
className="draggable"
draggable
onDragStart={(event) => handleDragStart(event)}
/>
</div>
</div>
);
}
export default App;
On the hovering and dragging the draggable, the below script invokes the changePosition
. This is a custom function that receives the dragged element reference with its x, y offset.
The changePosition()
calculates the x, and y offset about its center. By changing the x, y, coordinates, it reflects a drag and drop effect on the viewport.
The handleDrop
restricts the drag event within a boundary. When the user drags outside the boundary, it will bring the draggable back to the drop area.
src/App.js (Drag and drop event handlers)
import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
const [image, setImage] = useState({ logo_path: logo });
const handleDragStart = (event) => {
changePosition(event.target, event.clientX, event.clientY);
};
const handleDragOver = (event) => {
event.preventDefault();
changePosition(event.target, event.clientX, event.clientY);
};
const handleDrop = (event) => {
event.preventDefault();
// Limit the draggable boundary within the drop area
const container = document.querySelector('.drop-area');
const rect = container.getBoundingClientRect();
if (
// If within the boundary
event.clientX >= rect.left &&
event.clientX <= rect.right &&
event.clientY >= rect.top &&
event.clientY <= rect.bottom
) {
// When dragging outside the droparea
setImage({ logo_path: logo });
changePosition(event.target, rect.left + 100, rect.top + 100);
}
};
function changePosition(draggable, x, y) {
// Calculate draggable element x, y offset based on the center position
const offsetX = x - draggable.offsetWidth / 2;
const offsetY = y - draggable.offsetHeight / 2;
// Change draggable element position on a drop event
draggable.style.left = offsetX + "px";
draggable.style.top = offsetY + "px";
}
// returning JSX for a React drag and drop
}
export default App;