Drag and drop en React: lista ordenable y tablero kanban
Guía de drag and drop en React
Drag and drop en React: lista ordenable y kanban (dnd-kit) | We.Inc
Crea una lista ordenable y un tablero kanban en React con dnd-kit o con los eventos nativos de arrastre de HTML. Tablero en vivo en la página, movimiento por teclado incluido y código para copiar.
Para la mayoría de las apps de React, dnd-kit es la opción sólida más sencilla: un kit con licencia MIT que incluye sensores de puntero, táctiles y de teclado. Instala @dnd-kit/react, envuelve la zona en DragDropProvider, dale a cada tarjeta useSortable con un id, un índice y un grupo, y luego actualiza tu estado en onDragEnd. Los eventos nativos de arrastre de HTML también sirven, con más código escrito a mano.
Dos formas de añadir arrastrar y soltar
dnd-kit (@dnd-kit/react)
Drag and drop nativo de HTML
Instalación
npm install @dnd-kit/react
Nada, viene integrado en los navegadores
Teclado
Sensor de teclado incluido
Construyes tus propios controles de teclado
Táctil
Sensores táctiles y de puntero incluidos
Varía según el navegador; prueba en teléfonos
Listas ordenables
useSortable de @dnd-kit/react/sortable
Tus propios cálculos de índices en los manejadores de soltar
Ideal para
Tableros kanban, listas ordenables, cuadrículas
Soltar archivos o arrastres sencillos y puntuales
Abajo tienes un tablero que funciona y en el que puedes arrastrar tarjetas ahora mismo, con botones de flecha para quien no use ratón. Debajo encontrarás el código de dnd-kit para la misma lista ordenable y el tablero de varias columnas, además de la versión con eventos simples del navegador para comparar.
Arrastra una tarjeta dentro de su columna para reordenarla, o a otra columna para moverla.
¿Sin ratón? Llega a una tarjeta con Tab y usa sus botones de mover para cambiar su posición o su columna.
Copia primero la lista ordenable de dnd-kit y luego la versión kanban, que añade un grupo por columna.
Guarda los datos del tablero como estado simple organizado por columna y deja que onDragEnd genere la siguiente copia.
Da a cada elemento arrastrable un id estable sacado de tus datos. Los índices del array como ids fallan en cuanto los elementos se mueven.
Sal antes de tiempo cuando event.canceled sea true, para que pulsar Escape en mitad del arrastre deje el tablero intacto.
Guarda el nuevo orden en tu backend después de soltar y revierte el cambio si la petición falla.
Deja un hueco o un contorno visible donde caerá la tarjeta; la gente necesita ver el destino antes de soltar.
Las columnas vacías también necesitan una zona de soltar con algo de altura, o nunca se podrá soltar nada en ellas.
Preguntas frecuentes
¿Sigue siendo react-beautiful-dnd una buena opción?
Atlassian archivó el repositorio de react-beautiful-dnd y recomienda su sucesor, Pragmatic drag and drop. Para trabajo nuevo en React, dnd-kit o Pragmatic drag and drop son las opciones mantenidas activamente que conviene comparar.
¿Cuál es la diferencia entre @dnd-kit/core y @dnd-kit/react?
@dnd-kit/core junto con @dnd-kit/sortable es la pareja de paquetes de React con más recorrido. @dnd-kit/react es el adaptador más nuevo, construido sobre un núcleo independiente del framework que también impulsa los adaptadores de Vue, Svelte y Solid. El código nuevo puede empezar con @dnd-kit/react, como hace la documentación actual.
¿Por qué nunca se dispara mi evento drop con la API de HTML?
Un destino de soltar debe llamar a event.preventDefault() en su manejador dragover. Sin esa llamada, el navegador trata el elemento como un destino no válido y el evento drop nunca se envía.
¿Cómo hago accesible el arrastrar y soltar?
Haz que cada tarjeta pueda recibir el foco, ofrece una forma de cogerla, moverla y soltarla con el teclado, y anuncia el resultado en una región en vivo. dnd-kit incluye de serie un sensor de teclado y soporte de accesibilidad; con la API nativa lo añades todo tú.
Primero el estado, después el arrastre
Un tablero es un objeto de arrays: un array de ids de tarjetas por columna. El arrastre solo decide qué tarjeta se movió, de dónde venía y dónde cayó. Todas las librerías te dan esos cuatro datos, y tu código los convierte en un objeto nuevo.
Escribe esa función de movimiento como un helper puro y pruébala sin navegador. dnd-kit incluso trae uno, move de @dnd-kit/helpers, que recibe tus elementos y el evento de arrastre y devuelve la copia actualizada.
Por qué la API nativa es más difícil de lo que parece
El navegador dispara siete eventos (dragstart, drag, dragenter, dragleave, dragover, drop y dragend) y debes cancelar dragover en cada destino válido. Los datos viajan por event.dataTransfer como cadenas de texto, y solo puedes leerlos dentro del manejador drop.
No hay camino por teclado ni una forma integrada de animar las demás tarjetas para que se aparten. Eso está bien para soltar un archivo en una zona de subida, pero un tablero ordenable pronto se convierte en una pequeña librería propia.
Lista ordenable con dnd-kit
Instala con npm install @dnd-kit/react. Cada elemento conoce su propio índice; después de soltar, source.initialIndex y source.index te dicen adónde se movió.
SortableList.jsx
Reordena un array de nombres de tareas. Copiar y luego aplicar splice deja el estado anterior intacto.
Tablero kanban con dnd-kit
Añade un group a useSortable para que las tarjetas puedan viajar entre columnas. source.initialGroup y source.group son los nombres de la columna anterior y la nueva.
KanbanBoard.jsx
Tres columnas guardadas en un solo objeto. Mover dentro de una columna la reordena; mover a otra quita la tarjeta de un array y la inserta en el otro.
La misma idea con eventos nativos de arrastre de HTML
No hace falta ningún paquete. Fíjate en el preventDefault de onDragOver: sin él, el drop nunca se dispara.
NativeColumns.jsx
Mueve una tarjeta al final de la columna en la que se suelta. Reordenar dentro de una columna requeriría lógica de índices adicional.
Referencia de los eventos de arrastre de HTML
Los siete eventos de arrastre y dónde se disparan
Evento
Se dispara en
Cuándo
El elemento arrastrado
Empieza el arrastre; define dataTransfer aquí
El elemento arrastrado
Repetidamente mientras se arrastra
Un posible destino
El elemento arrastrado entra en él
Un posible destino
Repetidamente mientras está encima; invoca preventDefault para permitir soltar
Un posible destino
El elemento arrastrado sale de él
El destino
El elemento se suelta en un destino válido; lee dataTransfer aquí
El elemento arrastrado
El arrastre termina, soltado o cancelado
Por hacer
En curso
Hecho
Logo
Tabla de precios
Formulario de contacto
Sección hero
Dominio
{card} movida a {column}, posición {n}
Pruébalo: un tablero kanban que funciona
Arrastra tarjetas entre Por hacer, En curso y Hecho, o usa los botones de mover de cada tarjeta.