📋

dnd kitなるものを使ってみた

2024/08/12に公開

Drag&Dropできる機能を提供

Reactで、ドラッグ&ドロップする機能を実装したい。dnd kitという便利なパッケージを紹介してもらい使ってみました。

offical

add package:

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

今回は、ダミーの配列を並び替えるだけですが、TypeScriptで書いているので、データ型の書き方ではまりました。こちらの書き方を参考にしてもらえると、UIに表示されているリストを並び替えるロジックの学習はできます。

SortableList.tsxを作成

import React, { useState } from 'react';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
} from '@dnd-kit/core';
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

interface Item {
  id: string;
  name: string;
}

const SortableItem: React.FC<{ item: Item }> = ({ item }) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({ id: item.id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    border: '1px solid #ccc',
    padding: '10px',
    marginBottom: '5px',
    backgroundColor: 'white',
    cursor: 'move',
  };

  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      {item.name}
    </div>
  );
};

const SortableList: React.FC = () => {
  const [items, setItems] = useState<Item[]>([
    { id: '1', name: 'Item 1' },
    { id: '2', name: 'Item 2' },
    { id: '3', name: 'Item 3' },
  ]);

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;

    if (over && active.id !== over.id) {
      setItems((items) => {
        const oldIndex = items.findIndex((item) => item.id === active.id);
        const newIndex = items.findIndex((item) => item.id === over.id);

        return arrayMove(items, oldIndex, newIndex);
      });
    }
  };

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        <div>
          {items.map((item) => (
            <SortableItem key={item.id} item={item} />
          ))}
        </div>
      </SortableContext>
    </DndContext>
  );
};

export default SortableList;

App.tsxで、importするとサンプルを動かすことができます。

import SortableList from "./dndkit/SortableList";

function App() {
  return (
    <div className="App">
      <h1>Sortable List Example</h1>
      <SortableList />
    </div>
  );
}

export default App;

変更前:

変更後:

感想

公式やブログを見て、簡単そうかなと思ったら、データ型を定義しないといけなかったので、そこで詰まりました。これが使いこなせれば、リストの順番を並び替えることができるWebアプリのUIが作れますね。

Discussion