Reactでドラッグ・ドロップで並び替えをする方法
Reactでドラッグ・ドロップで並び替えを実現するには、react-beautiful-dndというライブラリが便利です。
以下に、react-beautiful-dndを使った基本的な実装例を示します。
まず、必要なライブラリのインストール手順を示します。
ライブラリのインストール
npm
npm install react-beautiful-dnd
yarn
yarn add react-beautiful-dnd
ソースコード例
import React, { useState } from 'react'; import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; const reorder = (list, startIndex, endIndex) => { const result = Array.from(list); const [removed] = result.splice(startIndex, 1); result.splice(endIndex, 0, removed); return result; }; const DragDropList = () => { const [items, setItems] = useState([ { id: '1', content: 'アイテム 1' }, { id: '2', content: 'アイテム 2' }, { id: '3', content: 'アイテム 3' }, ]); const onDragEnd = (result) => { if (!result.destination) { return; } const newItems = reorder( items, result.source.index, result.destination.index ); setItems(newItems); }; return ( <DragDropContext onDragEnd={onDragEnd}> <Droppable droppableId="droppable"> {(provided) => ( <div {...provided.droppableProps} ref={provided.innerRef}> {items.map((item, index) => ( <Draggable key={item.id} draggableId={item.id} index={index}> {(provided) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={{ userSelect: 'none', padding: 16, margin: '0 0 8px 0', minHeight: '50px', backgroundColor: '#ffffff', color: '#333333', border: '1px solid lightgrey', ...provided.draggableProps.style, }} > {item.content} </div> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> </DragDropContext> ); }; export default DragDropList;
説明
1. reorder関数
- リスト内のアイテムの順序を変更するためのユーティリティ関数です。
2. DragDropListコンポーネント
- アイテムの状態を管理するuseStateフックを使っています。
- DragDropContext、Droppable、Draggableコンポーネントを使って、ドラッグ&ドロップの機能を実装しています。
- onDragEndハンドラーはドラッグが終了した時に呼び出され、アイテムの新しい順序を設定します。
このコードを使用して、簡単にドラッグ&ドロップで並び替え可能なリストを作成できます。
const onDragEnd = (result) => { if (!result.destination) { alert('ドロップ先が無効です'); return; } const newItems = reorder( items, result.source.index, result.destination.index ); setItems(newItems); };