Drag & Drop
Regeln
- Verwenden Sie
@dnd-kit/core + @dnd-kit/sortable – moderne, zugängliche und touch-freundliche DnD-Bibliothek
- Sortierbare Listen: in
<SortableContext> einwickeln, jedes Element verwendet den useSortable()-Hook
- Kanban-Boards:
<DndContext> mit mehreren <SortableContext>-Containern – einer pro Spalte
- Datei-Ablagezonen:
react-dropzone oder natives onDragOver/onDrop mit e.dataTransfer.files
- Touch-Unterstützung: dnd-kit behandelt Touch nativ –
TouchSensor und PointerSensor mit Aktivierungsbeschränkungen verwenden
- Barrierefreiheit: dnd-kit bietet Tastatur-DnD sofort einsatzbereit –
KeyboardSensor mit sortableKeyboardCoordinates
- Optimistische Neuordnung: Zustand sofort beim Loslassen aktualisieren, Änderungen im Hintergrund an den Server senden, bei Fehlern zurücksetzen
- Drag Overlay:
<DragOverlay> für eine schwebende Vorschau des gezogenen Elements verwenden – besseres visuelles Feedback
Muster
import { DndContext, closestCenter, DragOverlay } from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
function SortableItem({ id, children }: { id: string; children: React.ReactNode }) {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
const style = { transform: CSS.Transform.toString(transform), transition };
return (
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
{children}
</div>
);
}
function SortableList({ items }: { items: Item[] }) {
const [activeId, setActiveId] = useState<string | null>(null);
return (
<DndContext
collisionDetection={closestCenter}
onDragStart={({ active }) => setActiveId(active.id)}
onDragEnd={handleDragEnd}
>
<SortableContext items={items.map((i) => i.id)} strategy={verticalListSortingStrategy}>
{items.map((item) => (
<SortableItem key={item.id} id={item.id}>{item.name}</SortableItem>
))}
</SortableContext>
<DragOverlay>{activeId ? <ItemPreview id={activeId} /> : null}</DragOverlay>
</DndContext>
);
}
Vermeiden
- Direkte Verwendung der HTML5-Drag-API – schlechte Touch-/Mobil-/Accessibility-Unterstützung
- Tastaturaccessibility vergessen – immer
KeyboardSensor einbeziehen
- Zustand während des Ziehens mutieren – nur in
onDragEnd aktualisieren
- Fehlender
DragOverlay – ohne ihn verschwindet das ursprüngliche Element während des Ziehens ohne visuelles Feedback