I recently attempted to create a drag and drop list feature in a React app without using any external packages. I came across a tutorial that claimed to achieve this.
This is the code I implemented:
class App extends React.Component {
state = {
items: ["3", "2", "1", "4"]
};
onDragStart = (e, index) => {
console.log("drag start!!!");
this.draggedItem = this.state.items[index];
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/html", e.target.parentNode);
e.dataTransfer.setDragImage(e.target.parentNode, 20, 20);
};
onDragOver = index => {
const draggedOverItem = this.state.items[index];
if (this.draggedItem === draggedOverItem) {
return;
}
let items = this.state.items.filter(item => item !== this.draggedItem);
items.splice(index, 0, this.draggedItem);
this.setState({ items });
};
onDragEnd = () => {
this.draggedIdx = null;
};
render() {
return (
<div className="App">
<main>
<h3>List of items</h3>
<ul>
{this.state.items.map((item, idx) => (
<li key={item} onDragOver={() => this.onDragOver(idx)}>
<div
className="drag"
draggable
onDragStart={e => this.onDragStart(e, idx)}
onDragEnd={this.onDragEnd}
style={{ cursor: "pointer" }}
/>
<span className="content" style={{ cursor: "pointer" }}>
{item}
</span>
</li>
))}
</ul>
</main>
</div>
);
}
}
Despite no errors showing up in the console, the drag functionality in the list doesn't work as intended. Occasionally, an item can be dragged but placing it where intended creates unexpected gaps or spaces: https://i.sstatic.net/VN4bn.png
The codesandbox with this implementation can be found here:https://codesandbox.io/s/angry-dewdney-xzhsi