dnd-kit-implementation について
dnd-kit-implementationは、dnd-kitでドラッグ&ドロップ操作を実装するための開発スキルです。ドラッグ中の対象に応じて、ソート可能なコンテナとドロップ先の動作を切り替える方法や状態更新パターンを示します。
主な機能
- 01ソートとドロップ動作の併用
- 02ドラッグ状況に応じたロジック切替
- 03IDプレフィックスによる要素の区別
- 04不変な状態更新
活用シーン
- 01カンバン列の並べ替えとカード移動
- 02フォルダー整理とファイル移動
- 03プレイリストや曲の並べ替え
- 04タスクリストの並べ替えとタスク移動
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ atman-33/ skills --skill dnd-kit-implementationインストール後、Claude Code で/dnd-kit-implementationを入力して読み込まれたか確認します。
同梱ファイルreferences/implementation-patterns.mdreferences/state-management.md
詳細
dnd-kit の実装ガイド
概要
このスキルでは、並べ替え可能なコンテナーとドロップ可能なターゲットを同時にサポートする dnd-kit ライブラリを使用して、ドラッグ&ドロップ機能を実装するためのパターンを紹介します。
核となる概念
useSortable と useDroppable を組み合わせるポイントは、ドラッグのコンテキストに基づく条件分岐です。
- アイテムをドラッグしているとき → コンテナーはドロップ専用のターゲットとして機能します
- コンテナーをドラッグしているとき → コンテナーは並べ替え可能な要素として機能します
現在ドラッグしている対象を検出し、適切な機能のみを有効にすることで実現できます。
実装パターン
コンポーネントの構造
const SortableDroppableContainer = ({ container }) => {
// useSortable for container reordering
const {
attributes,
listeners,
setNodeRef: setSortableRef,
transform,
transition,
isDragging,
} = useSortable({ id: container.id });
// useDroppable for receiving items
const { setNodeRef: setDroppableRef, isOver } = useDroppable({
id: container.id,
});
// Active element from context
const { active } = useDndContext();
// Determine behavior based on what's being dragged
const isItem = active?.id?.toString().startsWith('item-');
const isContainer = active?.id?.toString().startsWith('container-');
// Apply conditional refs
const setNodeRef = isItem ? setDroppableRef : setSortableRef;
return (
<div ref={setNodeRef} {...(isContainer ? attributes : {})} style={style}>
<div {...(isContainer ? listeners : {})}>{/* Drag handle */}</div>
{/* Container content */}
</div>
);
};
実装の重要なポイント
- 2つのフックの使用:同じコンポーネント内で
useSortableとuseDroppableの両方を使用します - コンテキストの検出:
useDndContext()を使用して、何がドラッグされているかを確認します - 条件付きの ref:ドラッグの状態に応じて、適切な ref を適用します
- ID の命名規則:種類を区別するために、
container-*やitem-*などのプレフィックスを使用します
ID の命名規則
// Containers
const containerId = `container-${id}`;
// Items
const itemId = `item-${id}`;
この規則により、条件分岐をすっきりと保ち、保守しやすくなります。
状態管理における重要事項
コンテナーのアイテムを更新するときは、必ず新しいオブジェクトを作成します。
// ❌ Won't trigger re-render
containers.items.push(newItem);
// ✅ Correct - creates new reference
setContainers(prev => prev.map(c =>
c.id === targetId
? { ...c, items: [...c.items, newItem] }
: c
));
一般的なユースケース
- カンバンボード:列の順序を変更し、カードを列間で移動します
- ファイル管理:フォルダーを再編成し、ファイルをフォルダーに移動します
- プレイリストエディター:プレイリストの順序を変更し、曲をプレイリストに追加します
- タスク管理ツール:タスクリストの順序を変更し、タスクをリスト間で移動します
参考資料
実装例とコードパターンの詳細については、以下を参照してください。
- implementation-patterns.md - TypeScript を使用したコンポーネントの完全な例
- state-management.md - 状態の更新パターンとよくある落とし穴
コメント
Markdown 対応