Se você já trabalhou com Jira, Trello, Confluence ou qualquer outro produto Atlassian, provavelmente encontrou uma funcionalidade de arrastar e soltar que permite os usuários arrastem itens por listas múltiplas (e às vezes enormes). É um recurso incrivelmente útil que sempre parece funcionar sem problemas, mas construir essa funcionalidade em um aplicativo pode ser um desafio.

O que é react-beautiful-dnd?

Acesse react-beautiful-dnd , a biblioteca de código aberto da Atlassian que permite aos desenvolvedores da web integre facilmente a funcionalidade de arrastar e soltar em seus aplicativos. react-beautiful-dnd é atualmente a biblioteca de arrastar e soltar mais popular no mundo React, e é o caminho a percorrer se você deseja implementar um recurso de arrastar e soltar em seu site.

Primeiro, vamos dar uma olhada em alguns dos recursos importantes do react-beautiful-dnd e ver o que o torna tão popular.

É altamente personalizável. A biblioteca tenta ser o mais sem cabeça possível, o que significa que existem apenas alguns estilos básicos em torno da animação. Eles são ajustáveis ​​e podem ser substituídos por sua própria implementação. Você pode até implementar seus próprios sensores para controlar as listas de arrastar e soltar com fontes de entrada adicionais além de um mouse, como um teclado (não há limites, conforme mostrado em os exemplos )
Nenhum nó DOM adicional é criado, o que significa que construir o layout é simples e previsível, garantindo que você possa projetar facilmente seus itens e listas de arrastar e soltar
Junto com o primeiro ponto, react-beautiful-dnd fornece uma ampla gama de opções e metadados que permitem criar combinações infinitas e diferentes casos de uso com ele

Confira uma lista abrangente de todos os recursos de documentação oficial .

Usando componentes react-beautiful-dnd para a funcionalidade de arrastar e soltar

A biblioteca está profundamente integrada ao ecossistema React, o que significa que toda a funcionalidade é construída e controlada em torno dos principais componentes do React.

DragDropContext

Este é o contexto que contém todas as informações sobre suas listas de arrastar e soltar. Ele é baseado no contexto React, então você deve envolver tudo relacionado a arrastar e soltar com este elemento para fazê-lo funcionar corretamente. Além disso, ele aceita a função onDrag, que é o retorno de chamada chave para controlar os dados de suas listas. Entraremos em mais detalhes posteriormente.

Droppable

Este elemento contém sua lista e a zona para soltar que será a fonte quando os elementos forem soltos. Ele deve ser identificado com um droppableId e deve ser agrupado em uma função que retorna um elemento React. Esta função é chamada com alguns parâmetros internos e um parâmetro de instantâneo contendo as informações sobre o estado da lista. Isso pode ser usado para estilização ou retornos de chamada para eventos em torno deste elemento.

Arrastável

Este é um contêiner para todos os elementos da lista. Você deve envolver cada um dos itens de sua lista com este elemento. Semelhante ao elemento Droppable, o elemento Children é uma função chamada com a propriedade Snapshot.

Para demonstrar como esses elementos são usados, vou mostrar alguns exemplos. Criaremos dois exemplos básicos para demonstrar os principais recursos da biblioteca. O primeiro será simples e mostrará como os elementos funcionam juntos. O segundo será mais avançado e conterá várias listas, semelhantes a uma placa Trello, para demonstrar os recursos desta biblioteca.

Construindo uma lista de arrastar e soltar com react-beautiful-dnd

Estrutura de dados

Para começar, precisamos de alguns dados para a demonstração:

interface DataElement { id: string; conteúdo: string;
} tipo List=DataElement []

Dentro desta estrutura, queremos visualizar uma lista de DataElements e possibilitar arrastar e soltar os elementos da lista.

Configurando os elementos de arrastar e soltar

Vamos primeiro criar os elementos de que precisamos para preparar nossa lista para arrastar e soltar. Como aprendemos acima, a primeira etapa é criar um DragDropContext que inclua tudo o que queremos em nossa lista.

Nele, criamos um contêiner que pode ser solto e mapeado sobre nossos DataElements, em seguida, renderizamos um elemento Draggable para cada um. O que é renderizado para cada elemento é com você. Para simplificar, renderizaremos um componente ListElement preparado que internamente leva apenas o estilo dos elementos para torná-lo bonito, mas não é relevante para o artigo.

function DragAndDropList () { Retorna ( {(fornecido, instantâneo)=> (

{elements.map ((item, index)=> ( {(fornecido, instantâneo)=> (

)} ))}

)} )
}

Para o propósito do exemplo, também omitiremos o estilo da lista, mas isso basicamente exibiria seus dados em uma lista com um abaixo do outro. A parte incrível de usar react-beautiful-dnd é que apenas escrevendo este código, já é possível capturar elementos. A lista e os elementos também são animados corretamente.

No entanto, como você pode ver no exemplo a seguir, se você mover o elemento para um local diferente, o elemento terminará brevemente no local correto, mas a lista retornará ao seu estado anterior e o elemento será em sua posição original.

A razão para isso é que a ordem dos elementos na matriz de dados subjacente permanece a mesma, já que react-beautiful-dnd não manipula seus dados e não deve ser responsável por isso. Em vez disso, react-beautiful-dnd apenas animará os estados e fornecerá os retornos de chamada adequados para lidar com seus dados.

É nosso trabalho colocar os dados da forma certa na hora certa. Portanto, agora precisamos definir um gancho quando o item for descartado e manipular corretamente nossos dados.

Primeiro, vamos colocar nossos dados em um estado React para torná-los mais fáceis de alterar e manipular:

function DragAndDropList () { const [items, setItems]=useState (baseData) Retorna (…)
}

Para entrar no ciclo de vida da animação de arrastar e soltar, podemos adicionar uma função onDragEnd ao nosso DragDropContext:

Agora precisamos implementar esta função dentro de nosso componente para moldar nosso estado da maneira certa quando esta função for chamada. Para obter todas as informações de que precisamos, a função recebe o seguinte objeto de resultado como um argumento. Este objeto possui a seguinte estrutura e propriedades:

interface DraggableLocation { droppableId: string; Número do índice;
} interface Combine { draggableId: string; droppableId: string;
} interface DragResult { razão:’DROP’|’CANCELAR’; destino ?: DraggableLocation; fonte: DraggableLocation; combinar ?: Combinar; modo:’FLUID’|’FOTO’; draggableId: DraggableId;
}

Este objeto resultante contém todas as informações sobre como precisamos manipular nossos dados para que não voltem à posição anterior.

As duas propriedades, destino e origem, são as mais importantes aqui. Como o nome sugere, a origem contém as informações onde o elemento estava antes e o destino contém onde o elemento foi descartado.

Ambas as propriedades contêm droppableId e index, ambos os quais precisamos para manipular nosso array de dados. Agora que temos tudo de que precisamos, vamos escrever a lógica de como queremos mudar nosso array de dados.

function DragAndDropList () { const [items, setItems]=useState (baseData) function onDragEnd (resultado) { const newItems=[… itens]; const [removido]=newItems.splice (result.source.index, 1); newItems.splice (result.destination.index, 0, removido); setItems (newItems) } Retorna (…)
}

Aqui, usamos o source.index e o destination.index para alterar nossos dados nos locais corretos.

Geralmente, isso é tudo de que precisamos para ter uma lista arrastar e soltar totalmente funcional. Mas antes de continuarmos, vamos adicionar uma pequena funcionalidade para torná-lo menos sujeito a erros. Como você pode ver na definição, a propriedade de destino pode ser indefinida. Isso significaria que o elemento não foi colocado em um elemento soltável.

Basta adicionar as linhas de código para evitar esse tipo de comportamento:

function onDragEnd (resultado) { if (! result.destination) { Retorna; } const newItems=[… itens]; const [removido]=newItems.splice (result.source.index, 1); newItems.splice (result.destination.index, 0, removido); setItems (newItems)
}

E é isso! Aqui está todo o fluxo em ação.

Criação de várias listas de arrastar e soltar com react-beautiful-dnd

Agora que vimos as funções básicas, vamos dar uma olhada em um caso de uso um pouco mais avançado, mas usado com mais frequência.

Talvez você tenha várias listas e queira arrastar e soltar itens não apenas dentro de cada lista, mas também entre as listas, como faria em um quadro Kanban. Com react-beautiful-dnd, você pode fazer isso. Vamos primeiro renderizar várias listas e tornar possível arrastar e soltar itens de uma lista para outra.

Semelhante ao primeiro exemplo, precisamos envolver tudo em DragDropContext. Além disso, precisamos criar uma constante que contenha as informações sobre quais listas queremos e iterar sobre ela para renderizar todos os elementos de listas desejados:

listas const=[‘todo’,’inProgress’,”feito”]; function DragList () { Retorna ( {lists.map ((listKey)=> ( ))} );
}

O elemento da lista que retornamos para cada elemento na matriz é quase o mesmo que no exemplo acima, com a única exceção sendo que ele não contém o estado dos dados ou a funcionalidade para manipulá-los.

Portanto, usaremos apenas a parte renderizada da lista e será semelhante a esta:

const DraggableElement=({prefix, elements})=> ( {(fornecido)=> (

{elements.map ((item, index)=> ( ))} {fornecido.placeholder}

)} )

É fundamental fornecer a cada lista e elemento Droppable um ID de propriedade exclusivo, chamado droppableId. Com esse ID, podemos identificar posteriormente de qual lista o elemento veio e em qual lista ele foi colocado.

Estado de gerenciamento

A parte complicada é decidir onde e como queremos manter nosso estado. Como podemos ter itens que mudam de lista para lista, precisamos mover o estado para o componente de empacotamento que contém todas as listas. Vamos começar criando um estado no componente DragList, que será parecido com isto:

dados const={ pendência: [ { id:’91583f67-0617-4df2-bd74-3c018460da6c’ listId:’todo’, conteúdo:’conteúdo aleatório’ }, … ]: em andamento: […] feito: […]
}

Idealmente, provavelmente usaríamos uma função redutora para o estado, mas para manter o exemplo curto, usaremos o gancho useState. Observe que temos um grande objeto que contém os dados de todas as nossas listas. Como fizemos em nosso exemplo de lista única de arrastar e soltar, também criamos a função onDrag:

const removeFromList=(lista, índice)=> { resultado const=Array.from (lista); const [removido]=result.splice (índice, 1); retorno [removido, resultado]
} const addToList=(lista, índice, elemento)=> { resultado const=Array.from (lista); result.splice (índice, 0, elemento); resultado de retorno
} const onDragEnd=(resultado)=> { if (! result.destination) { Retorna; } const listCopy={… elementos} const sourceList=listCopy [result.source.droppableId] const [removedElement, newSourceList]=removeFromList (sourceList, result.source.index) listCopy [result.source.droppableId]=newSourceList const destinationList=listCopy [result.destination.droppableId \] listCopy [result.destination.droppableId]=addToList (destinationList, result.destination.index, removedElement) setElements (listCopy)
}

Como você pode ver, o código em si é bastante semelhante ao exemplo de lista única, mas agora temos que considerar a respectiva lista identificada com o destino e a propriedade de origem.

Felizmente para nós, o objeto de resultado sempre fornece essas informações com a propriedade draggableId, que agora é bastante útil para saber de quais listas os elementos vêm e para onde eles vão em seguida. Agora você também pode arrastar e soltar itens entre listas.

Aqui está o exemplo completo.

Conclusão

Arrastar e soltar é uma funcionalidade amplamente usada que pode tornar seu aplicativo poderoso. A biblioteca react-beautiful-dnd fornece todas as funcionalidades necessárias para incorporar arrastar e soltar em seu aplicativo. É flexível, sem opinião e a animação funciona perfeitamente.

Como acontece com muitas coisas na programação de código aberto, a maioria dos problemas pode ser resolvida com precisão para (e por!) desenvolvedores usando bibliotecas. É bom ver empresas como a Atlassian disponibilizando suas soluções para o resto do mundo, para que os desenvolvedores da Web não tenham que criar recursos continuamente do zero.

A postagem Adicionando a funcionalidade de arrastar e soltar com react-beautiful-dnd apareceu primeiro no LogRocket Blog .