Drag and drop no React: lista ordenável e quadro kanban
Guia de drag and drop no React
Drag and drop no React: lista ordenável e kanban (dnd-kit) | We.Inc
Crie uma lista ordenável e um quadro kanban no React com dnd-kit ou com os eventos nativos de arrastar do HTML. Quadro ao vivo na página, movimentos por teclado incluídos e código para copiar.
Para a maioria dos apps React, o dnd-kit é a escolha sólida mais simples: um toolkit com licença MIT que já traz sensores de ponteiro, toque e teclado. Instale o @dnd-kit/react, envolva a área em DragDropProvider, dê a cada card um useSortable com id, index e group, e depois atualize o seu state no onDragEnd. Os eventos nativos de arrastar do HTML também funcionam, mas com mais código escrito à mão.
Duas formas de adicionar drag and drop
dnd-kit (@dnd-kit/react)
Drag and drop nativo do HTML
Instalação
npm install @dnd-kit/react
Nada, já vem nos navegadores
Teclado
Sensor de teclado incluído
Você cria os próprios controles de tecla
Toque
Sensores de toque e ponteiro incluídos
Varia conforme o navegador; teste em celulares
Listas ordenáveis
useSortable de @dnd-kit/react/sortable
Sua própria conta de índices nos handlers de drop
Ideal para
Quadros kanban, listas ordenáveis, grids
Soltar arquivos ou drops simples e pontuais
Abaixo há um quadro funcionando em que você pode arrastar os cards agora mesmo, com botões de seta para quem não usa mouse. Logo depois, você encontra o código com dnd-kit para a mesma lista ordenável e para o quadro com várias colunas, além da versão com os eventos simples do navegador para comparar.
Arraste um card dentro da coluna para reordená-lo, ou para outra coluna para movê-lo.
Sem mouse? Use Tab até um card e use os botões de mover para mudar a posição ou a coluna.
Copie primeiro a lista ordenável com dnd-kit, depois a versão kanban, que adiciona um group por coluna.
Guarde os dados do quadro como state simples, indexado por coluna, e deixe o onDragEnd gerar a próxima cópia.
Dê a cada item arrastável um id estável vindo dos seus dados. Usar índices do array como id quebra assim que os itens se movem.
Retorne cedo quando event.canceled for true, para que apertar Escape no meio do arraste deixe o quadro intacto.
Salve a nova ordem no seu backend depois do drop e desfaça a mudança se a requisição falhar.
Deixe um espaço ou contorno visível onde o card vai cair; as pessoas precisam ver o destino antes de soltar.
Colunas vazias ainda precisam de uma área de drop com alguma altura, senão nada nunca poderá ser solto nelas.
Perguntas frequentes
O react-beautiful-dnd ainda é uma boa escolha?
A Atlassian arquivou o repositório do react-beautiful-dnd e recomenda o sucessor, o Pragmatic drag and drop. Para projetos React novos, o dnd-kit e o Pragmatic drag and drop são as opções com manutenção ativa para comparar.
Qual é a diferença entre @dnd-kit/core e @dnd-kit/react?
O @dnd-kit/core com o @dnd-kit/sortable é a dupla de pacotes React mais antiga. O @dnd-kit/react é o adaptador mais novo, construído sobre um núcleo independente de framework que também alimenta os adaptadores para Vue, Svelte e Solid. Código novo pode começar com o @dnd-kit/react, como faz a documentação atual.
Por que o meu evento drop nunca dispara com a API do HTML?
Um alvo de drop precisa chamar event.preventDefault() no handler de dragover. Sem essa chamada, o navegador trata o elemento como um alvo inválido e o evento drop nunca é enviado.
Como deixar o drag and drop acessível?
Faça cada card receber foco, ofereça um jeito de pegar, mover e soltar pelo teclado e anuncie o resultado em uma live region. O dnd-kit já vem com sensor de teclado e suporte a acessibilidade; com a API nativa, você mesmo precisa adicionar tudo isso.
Primeiro o state, depois o arraste
Um quadro é um objeto de arrays: um array de ids de cards por coluna. O arraste só decide qual card se moveu, de onde ele veio e onde caiu. Toda biblioteca entrega esses quatro fatos, e o seu código os transforma em um objeto novo.
Escreva essa função de mover como um helper puro e teste sem navegador. O dnd-kit até traz uma pronta, move, de @dnd-kit/helpers, que recebe os seus itens e o evento de arraste e devolve a cópia atualizada.
Por que a API nativa é mais difícil do que parece
O navegador dispara sete eventos (dragstart, drag, dragenter, dragleave, dragover, drop e dragend) e você precisa cancelar o dragover em todo alvo válido. Os dados trafegam por event.dataTransfer como strings, e você só consegue lê-los dentro do handler de drop.
Não existe caminho pelo teclado nem um jeito embutido de animar os outros cards para abrir espaço. Isso basta para soltar um arquivo em uma área de upload, mas um quadro ordenável logo vira uma pequena biblioteca própria.
Lista ordenável com dnd-kit
Instale com npm install @dnd-kit/react. Cada item sabe o próprio índice; depois de um drop, source.initialIndex e source.index dizem para onde ele foi.
SortableList.jsx
Reordena um array de nomes de tarefas. Copiar e depois aplicar o splice mantém o state antigo intacto.
Quadro kanban com dnd-kit
Adicione um group ao useSortable para que os cards possam passar de uma coluna para outra. source.initialGroup e source.group são os nomes da coluna antiga e da nova.
KanbanBoard.jsx
Três colunas guardadas em um único objeto. Mover dentro de uma coluna a reordena; mover entre colunas tira o card de um array e o insere no outro.
A mesma ideia com os eventos nativos de arrastar do HTML
Nenhum pacote necessário. Repare no preventDefault em onDragOver: sem ele, o drop nunca dispara.
NativeColumns.jsx
Move um card para o fim da coluna em que ele é solto. Reordenar dentro de uma coluna exigiria lógica extra de índices.
Referência dos eventos de arrastar do HTML
Os sete eventos de arrastar e onde eles disparam
Evento
Dispara em
Quando
O elemento arrastado
O arraste começa; defina o dataTransfer aqui
O elemento arrastado
Repetidamente durante o arraste
Um possível alvo
O item arrastado entra nele
Um possível alvo
Repetidamente enquanto está sobre ele; chame preventDefault para permitir o drop
Um possível alvo
O item arrastado sai dele
O alvo
O item é solto em um alvo válido; leia o dataTransfer aqui
O elemento arrastado
O arraste termina, com drop ou cancelado
A fazer
Fazendo
Feito
Logo
Tabela de preços
Formulário de contato
Seção hero
Domínio
{card} movido para {column}, posição {n}
Experimente: um quadro kanban funcionando
Arraste os cards entre A fazer, Fazendo e Feito, ou use os botões de mover em cada card.