React Drag and Drop: sortierbare Liste und Kanban-Board
Leitfaden zu React Drag and Drop
React Drag and Drop: sortierbare Liste und Kanban (dnd-kit) | We.Inc
Baue in React eine sortierbare Liste und ein Kanban-Board mit dnd-kit oder mit den nativen HTML-Drag-Events. Live-Board auf der Seite, Tastatursteuerung inklusive, Code zum Kopieren.
Für die meisten React-Apps ist dnd-kit die einfachste solide Wahl: ein MIT-lizenziertes Toolkit mit eingebauten Sensoren für Pointer, Touch und Tastatur. Installiere @dnd-kit/react, umschließe den Bereich mit DragDropProvider, gib jeder Karte useSortable mit id, index und group und aktualisiere deinen State in onDragEnd. Die nativen HTML-Drag-Events funktionieren auch, brauchen aber mehr handgeschriebenen Code.
Zwei Wege zu Drag and Drop
dnd-kit (@dnd-kit/react)
Natives HTML Drag and Drop
Installation
npm install @dnd-kit/react
Nichts, in Browser eingebaut
Tastatur
Tastatursensor inklusive
Eigene Tastensteuerung nötig
Touch
Touch- und Pointer-Sensoren inklusive
Je nach Browser unterschiedlich; auf Handys testen
Sortierbare Listen
useSortable aus @dnd-kit/react/sortable
Eigene Indexberechnung in Drop-Handlern
Am besten für
Kanban-Boards, sortierbare Listen, Grids
Dateien ablegen oder einfache einmalige Drops
Unten findest du ein funktionierendes Board, auf dem du sofort Karten verschieben kannst, mit Pfeil-Buttons für alle, die keine Maus nutzen. Darunter steht der dnd-kit-Code für dieselbe sortierbare Liste und das mehrspaltige Board, dazu zum Vergleich die Version mit reinen Browser-Events.
Ziehe eine Karte innerhalb ihrer Spalte, um sie neu anzuordnen, oder in eine andere Spalte, um sie zu verschieben.
Keine Maus? Springe mit Tab zu einer Karte und nutze ihre Verschiebe-Buttons, um Position oder Spalte zu ändern.
Kopiere zuerst die sortierbare Liste mit dnd-kit, dann die Kanban-Version, die pro Spalte eine group hinzufügt.
Halte deine Board-Daten als einfachen State, nach Spalte geordnet, und lass onDragEnd die nächste Kopie erzeugen.
Gib jedem ziehbaren Element eine stabile id aus deinen Daten. Array-Indizes als ids gehen kaputt, sobald sich Elemente bewegen.
Brich früh ab, wenn event.canceled true ist, damit ein Druck auf Escape mitten im Ziehen das Board unverändert lässt.
Speichere die neue Reihenfolge nach dem Drop in deinem Backend und mache die Änderung rückgängig, wenn die Anfrage fehlschlägt.
Zeige eine sichtbare Lücke oder Umrandung, wo die Karte landen wird; Menschen müssen das Ziel sehen, bevor sie loslassen.
Auch leere Spalten brauchen eine Drop-Zone mit etwas Höhe, sonst kann nie etwas darin abgelegt werden.
Häufige Fragen
Ist react-beautiful-dnd noch eine gute Wahl?
Atlassian hat das Repository von react-beautiful-dnd archiviert und empfiehlt den Nachfolger Pragmatic drag and drop. Für neue React-Projekte sind dnd-kit und Pragmatic drag and drop die aktiv gepflegten Optionen, die du vergleichen solltest.
Was ist der Unterschied zwischen @dnd-kit/core und @dnd-kit/react?
@dnd-kit/core zusammen mit @dnd-kit/sortable ist das seit Langem bestehende React-Paarpaket. @dnd-kit/react ist der neuere Adapter, der auf einem frameworkunabhängigen Kern aufbaut, der auch die Adapter für Vue, Svelte und Solid antreibt. Neuer Code kann wie in der aktuellen Doku mit @dnd-kit/react starten.
Warum wird mein drop-Event mit der HTML-API nie ausgelöst?
Ein Drop-Ziel muss in seinem dragover-Handler event.preventDefault() aufrufen. Ohne diesen Aufruf behandelt der Browser das Element als ungültiges Ziel und sendet das drop-Event nie.
Wie mache ich Drag and Drop barrierefrei?
Mach jede Karte fokussierbar, biete per Tastatur eine Möglichkeit zum Aufnehmen, Verschieben und Ablegen und kündige das Ergebnis in einer Live-Region an. dnd-kit liefert einen Tastatursensor und Barrierefreiheit direkt mit; bei der nativen API baust du das alles selbst.
Erst der State, dann das Ziehen
Ein Board ist ein Objekt aus Arrays: ein Array mit Karten-ids pro Spalte. Das Ziehen entscheidet nur, welche Karte sich bewegt hat, woher sie kam und wo sie gelandet ist. Jede Bibliothek liefert dir diese vier Fakten, und dein Code macht daraus ein neues Objekt.
Schreibe diese Verschiebefunktion als reine Hilfsfunktion und teste sie ohne Browser. dnd-kit liefert sogar eine mit, move aus @dnd-kit/helpers, die deine Elemente und das Drag-Event entgegennimmt und die aktualisierte Kopie zurückgibt.
Warum die native API schwieriger ist, als sie aussieht
Der Browser löst sieben Events aus (dragstart, drag, dragenter, dragleave, dragover, drop und dragend), und du musst dragover auf jedem gültigen Ziel abbrechen. Daten reisen als Strings über event.dataTransfer, und du kannst sie nur im drop-Handler auslesen.
Es gibt keinen Weg per Tastatur und keine eingebaute Möglichkeit, die anderen Karten animiert aus dem Weg zu schieben. Für das Ablegen einer Datei in einem Upload-Bereich ist das in Ordnung, aber ein sortierbares Board wächst schnell zu einer eigenen kleinen Bibliothek heran.
Sortierbare Liste mit dnd-kit
Installiere mit npm install @dnd-kit/react. Jedes Element kennt seinen eigenen Index; nach einem Drop verraten dir source.initialIndex und source.index, wohin es verschoben wurde.
SortableList.jsx
Ordnet ein Array von Aufgabennamen neu. Erst kopieren, dann splice: So bleibt der alte State unverändert.
Kanban-Board mit dnd-kit
Füge useSortable eine group hinzu, damit Karten zwischen Spalten wandern können. source.initialGroup und source.group sind der alte und der neue Spaltenname.
KanbanBoard.jsx
Drei Spalten in einem Objekt. Verschieben innerhalb einer Spalte ordnet sie neu; Verschieben über Spalten hinweg entfernt die Karte aus einem Array und fügt sie in das andere ein.
Dieselbe Idee mit nativen HTML-Drag-Events
Kein Paket nötig. Achte auf preventDefault in onDragOver: Ohne diesen Aufruf wird drop nie ausgelöst.
NativeColumns.jsx
Verschiebt eine Karte ans Ende der Spalte, auf der sie abgelegt wird. Für das Neuordnen innerhalb einer Spalte wäre zusätzliche Indexlogik nötig.
Referenz der HTML-Drag-Events
Die sieben Drag-Events und wo sie ausgelöst werden
Event
Ausgelöst auf
Wann
Dem gezogenen Element
Das Ziehen beginnt; hier dataTransfer setzen
Dem gezogenen Element
Wiederholt während des Ziehens
Einem möglichen Ziel
Das gezogene Element betritt es
Einem möglichen Ziel
Wiederholt, solange es darüber ist; preventDefault aufrufen, um einen Drop zu erlauben
Einem möglichen Ziel
Das gezogene Element verlässt es
Dem Ziel
Das Element wird über einem gültigen Ziel losgelassen; hier dataTransfer auslesen
Dem gezogenen Element
Das Ziehen endet, abgelegt oder abgebrochen
Zu erledigen
In Arbeit
Erledigt
Logo
Preistabelle
Kontaktformular
Hero-Bereich
Domain
{card} verschoben nach {column}, Position {n}
Probier es aus: ein funktionierendes Kanban-Board
Ziehe Karten zwischen Zu erledigen, In Arbeit und Erledigt oder nutze die Verschiebe-Buttons auf jeder Karte.