Tips

Reactプロジェクトに最速でドラッグ&ドロップ機能を実装する【react-beautiful-dnd】

  • このエントリーをはてなブックマークに追加

Reactプロジェクトに簡単にドラッグ&ドロップ機能を実装する方法をご紹介します。

近年ではスマホ、タブレットの普及によりドラッグ&ドロップを使ったUIを実装する機会が増えています。

しかしながら0から実装するには座標の条件を考えたりして結構大変な作業です。

そこで今回は「react-beautiful-dnd」というライブラリを使用してドラッグ&ドロップを作成する方法を詳しく解説します。

JavaScriptの原理原則を理解しきれていない初心者の方でも実装することができますし、お試しで機能を追加してみるなんてときにも重宝します。

時間をかけずにドラッグ&ドロップ機能をあなたのReactプロジェクトに追加しましょう。

また動画も用意しているので必要に応じて活用してください。

react-beautiful-dndを使ったドラッグアンドドロップ

まずはライブラリのインストールが必要です。

# yarn
yarn add react-beautiful-dnd

# npm
npm install react-beautiful-dnd --save

インストールが完了したらマニュアルに記載されているコンポーネントを使ってコーディングしていく流れです。

react-beautiful-dndはコンポーネントやprops名が事前に決められていて、自分の作りたいイメージに合うものを試しながら作ることになるでしょう。

本記事では一番シンプルなドラッグ&ドロップを作成してみます。

import React from "react";
// コンポーネントの読み込み
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";

const DragDrop = () => {
  return (
    <>
      <DragDropContext>
        <Droppable droppableId="chars">
          {(provided) => (
            <div
              className="todoList"
              {...provided.droppableProps}
              ref={provided.innerRef}
            >
              <Draggable draggableId="todo0" index={0}>
                {(provided) => (
                  <div
                    className="todo"
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    ref={provided.innerRef}
                  >
                    料理
                  </div>
                )}
              </Draggable>
              <Draggable draggableId="todo1" index={1}>
                {(provided) => (
                  <div
                    className="todo"
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    ref={provided.innerRef}
                  >
                    掃除
                  </div>
                )}
              </Draggable>
              <Draggable draggableId="todo2" index={2}>
                {(provided) => (
                  <div
                    className="todo"
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    ref={provided.innerRef}
                  >
                    買い物
                  </div>
                )}
              </Draggable>
              <Draggable draggableId="todo3" index={3}>
                {(provided) => (
                  <div
                    className="todo"
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    ref={provided.innerRef}
                  >
                    洗濯
                  </div>
                )}
              </Draggable>
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </>
  );
};

export default DragDrop;
.todoList {
  margin: 16px;
  width: 400px;
}
.todo {
  padding: 8px 16px;
  background: #eee;
  border-bottom: 1px solid #fff;
}

DragDropContext、Drappable、Draggableという3つのコンポーネントを利用しました。

react-beautiful-dndのコンポーネントは通常のコンポーネントのようにimport文が必要なので忘れないように書きましょう。

3つのコンポーネントのイメージは以下のような形です。

https://github.com/atlassian/react-beautiful-dnd/blob/master/README.md#documentation-

DragDropContext:ドラッグ&ドロップを表示するエリア
Droppable:ドロップできるエリア
Draggable:ドラッグするアイテム

という感じですね。

Droppableコンポーネントはprovidedというオブジェクトがあり、こちらにドロップできるエリアに関する情報があります。

同じようにDraggableコンポーネントもprovidedというオブジェクトがあり、こちらにドラッグするアイテムに関する情報があります。

そのためアイテムをドロップしたときに、ドロップ先の要素を判別してアイテムの順番を自動で変更するようになっています。

アイテムの判別にはdraggableIdとindexの値を参照するわけです。

先ほどのコードでは「料理」「洗濯」などベタ書きで並べていましたが実務を想定すると、データに格納してある状態からmapメソッドなど繰り返し処理で表示させることになります。

例えば以下のような感じです。

import React from "react";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
const DragDrop = () => {
 // ドラッグ&ドロップするアイテムのリスト
  const tasks = [
    {
      id: "todo0",
      text: "料理",
    },
    {
      id: "todo1",
      text: "掃除",
    },
    {
      id: "todo2",
      text: "買い物",
    },
    {
      id: "todo3",
      text: "洗濯",
    },
  ];

  return (
    <>
      <DragDropContext>
        <Droppable droppableId="chars">
          {(provided) => (
            <div
              className="todoList"
              {...provided.droppableProps}
              ref={provided.innerRef}
            >
              {tasks.map((task, index) => (
                <Draggable draggableId={task.id} index={index}>
                  {(provided) => (
                    <div
                      className="todo"
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      ref={provided.innerRef}
                    >
                      {task.text}
                    </div>
                  )}
                </Draggable>
              ))}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </>
  );
};

export default DragDrop;

ドラッグアンドドロップは頻出の機能ですが自力で作るには労力がかかるのでライブラリに頼ってみましょう。

mapメソッドについて詳しく知りたい方は過去に解説したので以下よりご覧ください。

初心者が混同しがちなforEachとの違いにも触れています。

また今回参考にした本は以下になりますのでよければどうぞ。

今回参考にした本はこちら

  • このエントリーをはてなブックマークに追加