Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Drag & Drop Multiple Elements In React?

This is my first question on StackOverflow. I want to build a little game with React, where users can drag and drop tetrominos onto a grid and also reposition or rotating them to their liking. The tetrominos are represented by a matrix and then every block gets rendered in a li element.

Example for the z-tetromino: [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0]

Unfortunately I cannot post images yet, that would make things easier.

The grid is too respresented by a matrix.

Now what I want to do is basically drag and drop these block matrices onto the grid, so that the values in the grid change accordingly (0 → 1 etc.).

The problem is, I have no clue how to drag multiple li elements at once with the standard HTML5 DnD API or with React DnD. When the user clicks on one li element of a certain tetromino, the whole piece should move. Maybe I could solve this using jQuery UI, but since in React no direct DOM manipulation is allowed, I'm left wondering how to do it.

I tried to drag one block onto the grid which worked semi optimally, because one block took the place of an entire row of grid blocks, even with display: inline-block set in CSS.

Here is some simple code from the first experiment.

onDragStart = e => {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text', e.target.id);
    // e.dataTransfer.setDragImage(e.target.parentNode, 20, 20);
  };

  handleDrop = e => {
    const pieceOrder = e.dataTransfer.getData('text');
    // console.log(document.getElementById(pieceOrder));
    // e.target.appendChild(document.getElementById(pieceOrder));
    // console.log(pieceOrder);
    e.target.replaceWith(document.getElementById(pieceOrder));
    e.target.remove();
  };

renderEmptyBoardCell(i) {
    return (
      <li key={i} className="emptyBoardCell" onDragOver={(e) => e.preventDefault()} onDrop={(e) => this.handleDrop(e)}>></li>
    );
  }

  renderTemplateBoardCell(i) {
    return (
      <li key={i} className="templateBoardCell" onDragOver={(e) => e.preventDefault()} onDrop={(e) => this.handleDrop(e)}>></li>
    );
  }

  renderEmptyCell(i) {
    return (
      <li key={i} className="emptyCell"></li>
    );
  }

  renderFilledCell(piece_config, i) {
    return (
      <li key={i} id={i} className={`filledCell ${piece_config}`} draggable onDragStart={this.onDragStart}></li>
    );
  }

So the question is, would that be theoretically possible with React DnD or any other library? If yes, what would be the approximate solution to DnD multiple elements at once.

Thanks for your time!

like image 422
Fallc Avatar asked Oct 24 '25 02:10

Fallc


1 Answers

In case anyone is looking for a solution in 2020. Here is my current solution with react-dnd and react hooks. You can try the live demo here.

Here is another simpler example, you can check out the codesandbox here.

like image 117
Lala La Avatar answered Oct 26 '25 16:10

Lala La



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!