Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 20, 2022 01:33 pm GMT

Creando un app que usa Drag and Drop con React sin libreras !

Las aplicaciones que usan drag and drop son muy comunes hoy en da, son excelentes para la experiencia de usuario dentro de un app. Y probablemente te gustara implementarlo en tu prximo proyecto.

En esta ocasin, te enseare como realizar una aplicacin que tenga la funcionalidad de drag & drop, pero sin usar alguna librera externa, solamente con React JS.

Nota: Este post requiere que sepas las bases de React con TypeScript (hooks bsicos y custom hooks).

Cualquier tipo de Feedback es bienvenido, gracias y espero disfrutes el articulo.

Tabla de contenido.

Tecnologas a utilizar.

Creando el proyecto.

Primeros pasos.

Creando nuestras tarjetas.

Creando los contenedores para nuestras tarjetas.

Definiendo el tipo e interfaz para la informacin de las tarjetas.

Creando el componente DragAndDrop.tsx

Agregando algunos datos para crear tarjetas.

Mostrando algunas tarjetas.

Realizando la funcional de Drag.

Realizando la funcional de Drop.

Creando el estado para mantener las tarjetas.

Realizando las funciones para hacer el drop en los contenedores.

Opcional. Refactorizacin del cdigo en DragAndDrop.tsx

Conclusin.

Demostracin en vivo.

Cdigo fuente.

Tecnologas a utilizar.

  • React JS (version 18)
  • Vite JS
  • TypeScript
  • CSS vanilla (Los estilos los encuentras en el repositorio al final de este post)

Creando el proyecto.

Al proyecto le colocaremos el nombre de: dnd-app (opcional, tu le puedes poner el nombre que gustes).

npm init vite@latest

Creamos el proyecto con Vite JS y seleccionamos React con TypeScript.

Luego ejecutamos el siguiente comando para navegar al directorio que se acaba de crear.

cd dnd-app

Luego instalamos las dependencias.

npm install

Despus abrimos el proyecto en un editor de cdigo (en mi caso VS code).

code .

Luego con este comando levantaremos el servidor de desarrollo, y finalmente vamos a un navegador y accedemos a http://localhost:5173 (en vite version 2 el puerto era localhost:3000, pero en la nueva version el puerto es localhost:5173)

npm run dev

Primeros pasos.

De una vez, creamos la carpeta src/components y agregamos el archivo Title.tsx y dentro agregamos:

export const Title = () => {    return (        <div className="title flex">            <h1>Creating basic Drag & Drop  </h1>            <span>( without external libraries )</span>        </div>    )}

Ahora, dentro del archivo src/App.tsx borramos todo el contenido del archivo y colocamos un componente funcional que muestre el titulo que acabamos de crear.

import { Title } from "./components/Title"const App = () => {  return (    <div className="container-main flex">        <Title />    </div>  )}export default App

Debera de verse as :

Title

Creando nuestras tarjetas.

Dentro de la carpeta src/components agregamos el archivo CardItem.tsx

Por el momento no recibir ninguna prop, lo har despus.

export const CardItem = () => {    return (        <div className='card-container'>            <p>content</p>        </div>    )}

Aun NO usaremos el componente Card en un archivo, pero si quieres puedes importarlo en el archivo src/App.tsx para que puedas darle algunos estilos y verlos en pantalla.

Creando los contenedores para nuestras tarjetas.

Ahora vamos a crear nuestro contenedor para las tarjetas.
Dentro de la carpeta src/components agregamos el archivo ContainerCards.tsx y agregamos lo siguiente:

Este componente por el momento recibe como parmetro el estado ( puedes ver de que tipo es el Status)

import { Status } from '../interfaces'interface Props {  status: Status}export const ContainerCards = ({ status }: Props) => {    return (        <div className="layout-cards" >            <p>{status} hero</p>            {/* Cards */}        </div>    )}

Definiendo el tipo e interfaz para la informacin de las tarjetas.

El type Status es el siguiente:

export type Status = 'good' | 'bad' | 'normal'

Este tipo esta en dentro de la carpeta src/interfaces dentro de un archivo index.ts (el cual deben ir creando, ya que el type Status lo usaremos en varios archivos )

Aprovechando que se estn creando el index.ts en src/interfaces tambin agreguen la siguiente interfaz.

Asi es como lucirn los datos de las tarjetas.

export interface Data {    id: number    content: string    status: Status}

Creando el componente DragAndDrop.tsx

Bueno, hasta aqu ya hemos creado el componente que contendr las tarjetas, pero necesitamos 3 contenedores de tarjetas:

  • Uno para lo heroes buenos.
  • Uno para lo heroes normales.
  • Uno para lo heroes malos.

Dentro de la carpeta src/components agregamos el archivo DragAndDrop.tsx y agregamos lo siguiente:

import { Status } from "../interfaces"import { ContainerCards } from "./ContainerCards"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {    return (        <div className="grid">            {                typesHero.map( container => (                    <ContainerCards                        status={container}                        key={container}                    />                ))            }        </div>    )}

Este componente debemos agregarlo al src/App.tsx

import { DragAndDrop} from "./components/DragAndDrop"import { Title } from "./components/Title"const App = () => {  return (    <div className="container-main flex">      <Title />      <DragAndDrop />    </div>  )}export default App

Debera de verse algo como esto por el momento ...
Grid without cards

Listo ya tenemos los contenedores donde se podrn soltar las tarjetas y clasificarlas.

Ahora necesitamos crear algunas tarjetas.

Agregando algunos datos para crear tarjetas.

Ahora creamos una carpeta src/assets y dentro un archivo index.ts el cual contendr un listado con datos para rellenar las tarjetas.

import { Data } from "../interfaces";export const data: Data[] = [    {        id: 1,        content: 'Aqua-man',        status: 'good'    },    {        id: 2,        content: 'Flash',        status: 'normal'    },    {        id: 3,        content: 'Green Lantern',        status: 'good'    },    {        id: 4,        content: 'Batman',        status: 'bad'    },]

Ahora, devuelta en src/componentes/DragAndDrop.tsx en componente ContainerCards le pasamos una nueva prop llamada items a dicha prop le pasamos como valor la data que hemos creado en la carpeta src/assets

import { ContainerCards } from "./ContainerCards"import { Status } from "../interfaces"import { data } from "../assets"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {    return (        <div className="grid">            {                typesHero.map( container => (                    <ContainerCards                        status={container}                        key={container}                        items={data}                    />                ))            }        </div>    )}

Esto nos marcara error ya que items no es una propiedad que ContainerCards este esperando.

Pero eso lo arreglamos en la siguiente seccin.

Mostrando algunas tarjetas.

Para mostrar algunas tarjetas, necesitamos hacer unos cambios en los parmetros de cada componente.

1 - Primero el componente src/components/CardItem.tsx

Recibir como props la data que es de tipo Data, la que habamos definido con anterioridad .

De una vez mostramos la propiedad content dentro de data.

import { Data } from "../interfaces"interface Props {    data: Data}export const CardItem = ({ data, handleDragging }: Props) => {    return (        <div className='card-container'>            <p>{data.content}</p>        </div>    )}

2 - En el componente src/components/ContainerCards.tsx cambiamos las interfaz de Props agregando la propiedad items que es un listado de Data y la desestructuramos en el componente

import { Data, Status } from "../interfaces"interface Props {    items: Data[]    status: Status}export const ContainerCards = ({ items = [], status }: Props) => {    return (        <div className="layout-cards">            <p>{status} hero</p>        </div>    )}

Luego debajo de la etiqueta p realizamos una iteracin a los items.
Y retornamos la el CardItem.tsx mandando el item a la propiedad de data del CardItem

import { Data, Status } from "../interfaces"import { CardItem } from "./CardItem"interface Props {    items: Data[]    status: Status}export const ContainerCards = ({ items = [], status}: Props) => {    return (        <div className="layout-cards">            <p>{status} hero</p>            {                items.map(item => (                    <CardItem                        data={item}                        key={item.id}                    />                ))            }        </div>    )}

Esto te dar una advertencia de que las key se repiten

Esto es debido a que estamos renderizando 3 veces el ContainerCards.

Pero espera la nica propiedad que har la diferencia entre estos 3 componentes es el status

Por lo que haremos la siguiente condicin:

  • Si el estado que recibe el componente ContainerCards es igual al estado del item (o sea del super hroe) entonces renderizalo, de lo contrario retorna falso.
import { Data, Status } from "../interfaces"import { CardItem } from "./CardItem"interface Props {    items: Data[]    status: Status}export const ContainerCards = ({ items = [], status }: Props) => {    return (        <div className="layout-cards">            <p>{status} hero</p>            {                items.map(item => (                    status === item.status                    && <CardItem                        data={item}                        key={item.id}                    />                ))            }        </div>    )}

Y asi evitamos el conflicto con las llaves y se clasificaran las tarjetas de la siguiente manera ...

Grid and cards

Realizando la funcional de Drag.

Para realizar la funcionalidad de drag, primero vamos a definir un estado y una funcin en src/components/DragAndDrop.tsx

  • El estado nos ayudara a saber si si esta haciendo drag, y asi cambiar los estilos de.

    • Y por defecto sera false, ya que al inicio de la aplicacin no se estar haciendo haciendo drag.
    • Solo sera true cuando se arrastre alguna tarjeta.
  • La funcin, la cual recibe un valor booleano, nos ayudara a cambiar al valor al estado, esto lo hado para no pasar el setter setIsDragging como prop.

Pasamos como prop al componente ContainerCards:

  • isDragging, tendr el valor del estado
  • handleDragging, sera la funcin que creamos para actualizar el estado.
import { ContainerCards } from "./ContainerCards"import { data } from "../assets"import { Status } from "../interfaces"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {  const [isDragging, setIsDragging] = useState(false)  const handleDragging = (dragging: boolean) => setIsDragging(dragging)    return (        <div className="grid">            {                typesHero.map(container => (                    <ContainerCards                        items={data}                        status={container}                        key={container}                        isDragging={isDragging}                        handleDragging={handleDragging}                    />                ))            }        </div>    )}

Esto marcara error porque ContainerCards no espera esas propiedades.

Asi que vamos a tener que cambiar la interfaz de ContainerCards
El el archivo src/components/ContainerCards.tsx

interface Props {    items: Data[]    status: Status    isDragging: boolean    handleDragging: (dragging: boolean) => void}

Y de una vez obtenemos esas props.

  • Nota que en el className del div colocamos una condicin, donde si isDragging es verdadero entonces agregamos la clase layout-dragging. Esta clase solo cambiara el color de fondo y el borde del contenedor, cuando se arrastre una tarjeta.

  • Nota, que tambin pasamos una nueva prop al CardItem la cual es handleDragging, esto es porque la tarjeta es el componente que va actualizar el estado que creamos con anterioridad.

import { CardItem } from "./CardItem"import { Data, Status } from "../interfaces"interface Props {    items: Data[]    status: Status    isDragging: boolean    handleDragging: (dragging: boolean) => void}export const ContainerCards = ({ items = [], status, isDragging, handleDragging }: Props) => {    return (        <div            className={`layout-cards ${isDragging ? 'layout-dragging' : ''}`}        >            <p>{status} hero</p>            {                items.map(item => (                    status === item.status                    && <CardItem                        data={item}                        key={item.id}                        handleDragging={handleDragging}                    />                ))            }        </div>    )}

El CardItem nos marcara error ya que no espera la propiedad handleDragging, por lo que debemos modificar su interfaz.

Ahora en el archivo src/components/CardItem.tsx modificamos la interfaz

interface Props {    data: Data,    handleDragging: (dragging: boolean) => void}

Y ahora si, empezamos a agregar la funcionalidad de drag en este componente.
Primero al div que es el toda la tarjeta, le agregamos el atributo draggable para indicar que este componente se puede arrastrar.

import { Data } from "../interfaces"interface Props {    data: Data,    handleDragging: (dragging: boolean) => void}export const CardItem = ({ data, handleDragging }: Props) => {    return (        <div            className='card-container'            draggable        >            <p>{data.content}</p>        </div>    )}

Luego agregamos el atributo onDragEnd que va a ejecutar la funcin handleDragEnd.

Dicha funcin lo nico que har es colocar el valor del estado isDragging en false, porque cuando se ejecute onDragEnd ya se habr dejado de arrastrar la tarjeta por lo que tenemos que quitar los estilos de cuando se hace drag, o sea volver todos los estilos como al inicio.

import { Data } from "../interfaces"interface Props {    data: Data,    handleDragging: (dragging: boolean) => void}export const CardItem = ({ data, handleDragging }: Props) => {    const handleDragEnd = () => handleDragging(false)    return (        <div            className='card-container'            draggable            onDragEnd={handleDragEnd}        >            <p>{data.content}</p>        </div>    )}

Luego agregamos el atributo onDragStart (se ejecuta cuando se empieza arrastrar el componente, si no le colocramos el atributo draggable, entonces onDragStart no se ejecutara).

onDragStart va ejecutar la funcin handleDragStart.

Esta funcin recibe el evento y dentro del evento hay una propiedad que nos interesa que es la de dataTransfer.

La propiedad dataTransfer nos permite contener u obtener datos cuando se esta arrastrando un elemento.

La propiedad setData dentro de dataTransfer, establece los datos que queremos contener al momento de arrastrar un elemento, y recibe dos parmetros:

  • format: es un identificador que representa la data a contener. Puede ser lo que sea pero tiene que ser un string. En este caso, le colocaremos la palabra 'card'.

  • data: es la informacin que queremos contener mientras se hace el arrastre del elemento. Solo acepta un string. En este caso, almacenaremos el id de la tarjeta.

NOTA: tambin existe una propiedad dentro de dataTransfer llamada clearData que limpia el cache de los datos que almacenamos. En este caso no es necesario ejecutarlo, ya que vamos a estar sobrescribiendo el mismo identificador 'card'.

Despus de contener la data, ejecutamos handleDragging mandando el valor de true para indicar al usuario que estamos arrastrando un elemento.

import { Data } from "../interfaces"interface Props {    data: Data,    handleDragging: (dragging: boolean) => void}export const CardItem = ({ data, handleDragging }: Props) => {    const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {        e.dataTransfer.setData('card', `${data.id}`)        handleDragging(true)    }    const handleDragEnd = () => handleDragging(false)    return (        <div            className='card-container'            draggable            onDragStart={handleDragStart}            onDragEnd={handleDragEnd}        >            <p>{data.content}</p>        </div>    )}

Y asi tendramos la parte de arrastrar un elemento, ya tendramos la informacin contenida lista para obtenerla cuando se suelte en otro contenedor.

Asi se vera cuando arrastramos una tarjeta, cambia el diseo de los contenedores indicando que son los lugares donde puedes soltar la tarjeta.

Grid dragging effect

Realizando la funcional de Drop.

Antes de hacer la parte de soltar el elemento, debemos realizar otras cosas antes.

Creando el estado para mantener las tarjetas.

Primero establecer la lista de heroes en un estado y poder actualizarla cuando se suelte la tarjeta en otro contenedor,en ese momento actualizaramos la propiedad status del hroe, lo que provocara que se vuelva a renderizar de nuevo el listado organizando las tarjetas que cambiaron.

Para eso vamos a src/components/DragAndDrop.tsx y creamos un nuevo estado.
Su valor inicial va a ser la data que hemos definido previamente en src/assets.

import { data } from "../assets"const [listItems, setListItems] = useState<Data[]>(data)

Y ahora, al momento de renderizar el componente ContainerCards, en vez de pasar el valor de data a la prop de items, le mandaremos el valor del estado listItems.

import { ContainerCards } from "./ContainerCards"import { data } from "../assets"import { Status } from "../interfaces"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {  const [isDragging, setIsDragging] = useState(false)  const [listItems, setListItems] = useState<Data[]>(data)  const handleDragging = (dragging: boolean) => setIsDragging(dragging)    return (        <div className="grid">            {                typesHero.map(container => (                    <ContainerCards                        items={listItems}                        status={container}                        key={container}                        isDragging={isDragging}                        handleDragging={handleDragging}                    />                ))            }        </div>    )}

Despus crearemos una funcin para actualizar el estado de la listItems.
La llamaremos handleUpdateList, y recibir dos parmetros:

  • id: el identificador de la tarjeta, sera de tipo nmero.
  • status: el nuevo estado de la tarjeta, sera de tipo Status.

Dentro de la funcin ...

1 - Primero buscaremos el elemento en el valor del estado listItems, mediante el ID.

2 - Evaluaremos si los datos existen y si el status que nos pasan es diferente al status que ya tiene, entonces haremos los cambios en el estado.

3 - Dentro de la condicin, accedemos a la tarjeta encontrada y actualizaremos su propiedad status asignndole el nuevo status que nos llega por parmetro en la funcin.

4 - Llamamos al setListItems para actualizar el estado, colocando:

  • La tarjeta con su propiedad status actualizada.

  • Un nuevo arreglo, filtrando los elementos para quitar el tarjeta que estamos actualizando y evitar que se duplique la informacin.

Ahora, al componente ContainerCards le agregamos una nueva propiedad llamada handleUpdateList y le mandamos la funcin que acabamos de crear handleUpdateList.

import { ContainerCards } from "./ContainerCards"import { data } from "../assets"import { Status } from "../interfaces"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {  const [isDragging, setIsDragging] = useState(false)  const [listItems, setListItems] = useState<Data[]>(data)  const handleDragging = (dragging: boolean) => setIsDragging(dragging)  const handleUpdateList = (id: number, status: Status) => {       let card = listItems.find(item => item.id === id)       if (card && card.status !== status) {           card.status = status           setListItems( prev => ([                card!,                ...prev.filter(item => item.id !== id)            ]))       }   }    return (        <div className="grid">            {                typesHero.map(container => (                    <ContainerCards                        items={listItems}                        status={container}                        key={container}                        isDragging={isDragging}                        handleDragging={handleDragging}                        handleUpdateList={handleUpdateList}                    />                ))            }        </div>    )}

Esto nos marcara error, porque el componente ContainerCards no espera la propiedad handleUpdateList, asi que debemos actualizar la interfaz de ContainerCards.

En src/components/ContainerCards.tsx:

interface Props {    items: Data[]    status: Status    isDragging: boolean    handleDragging: (dragging: boolean) => void    handleUpdateList: (id: number, status: Status) => void}

Realizando las funciones para hacer el drop en los contenedores.

Estamos en src/components/ContainerCards.tsx.

Dentro del componente vamos a establecer dos propiedades nuevas al elemento div.

  • onDragOver: se produce cuando un elemento que es arrastrable se arrastra sobre un objetivo de soltar valido. Le pasamos la funcin handleDragOver, que crearemos en un instante.

  • onDrop: se produce cuando el elemento arrastrado se deja caer. Le pasamos la funcin handleDrop, que crearemos en un instante.

<div    className={`layout-cards ${isDragging ? 'layout-dragging' : ''}`}    onDragOver={handleDragOver}    onDrop={handleDrop}>    <p>{status} hero</p>    {        items.map(item => (            status === item.status            && <CardItem                data={item}                key={item.id}                handleDragging={handleDragging}            />        ))    }</div>

La funcin handleDragOver solo har esto.
Primero, recibir el evento que emite onDragOver.

Ya que por defecto los datos no pueden ser soltados en otros elementos y para permitir soltarlos debemos evitar el comportamiento por defecto.

const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {    e.preventDefault()}

Ahora la funcin handleDrop

  • Primero, recibir el evento que emite onDrop.

  • Dentro de la funcin, evitamos el comportamiento por defecto, el cual se nota mas con imgenes (cuando soltamos una imagen en un lugar de nuestra app, abre la imagen, sacndonos de la app).

  • Entonces, del evento, obtenemos la propiedad dataTransfer y mediante la propiedad de getData de dataTransfer, la ejecutamos mandando el identificador del cual obtendremos el ID de la tarjeta.

    • El signo de + al inicio de e.dataTransfer.getData('card') es para convertir el valor a un nmero.
  • Luego llamaremos la funcin handleUpdateList que el componente nos pasa por props, (hay que desestructurarlo del componente).

    • Le pasamos primero el id que obtuvimos de la propiedad getData de dataTransfer ya convertido en nmero.
    • Despus le pasamos el status que recibimos por props en el componente.
  • Finalmente llamamos handleDragging mandando el valor de false para indicar al usuario que ya no estamos arrastrando nada.

const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {    e.preventDefault()    const id = +e.dataTransfer.getData('card')    handleUpdateList(id, status)    handleDragging(false)}

As se vera el cdigo de src/components/ContainerCards.tsx

import { Data, Status } from "../interfaces"import { CardItem } from "./CardItem"interface Props {    items: Data[]    status: Status    isDragging: boolean    handleUpdateList: (id: number, status: Status) => void    handleDragging: (dragging: boolean) => void}export const ContainerCards = ({ items = [], status, isDragging, handleDragging, handleUpdateList }: Props) => {    const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {        e.preventDefault()        handleUpdateList(+e.dataTransfer.getData('card'), status)        handleDragging(false)    }    const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => e.preventDefault()    return (        <div            className={`layout-cards ${isDragging ? 'layout-dragging' : ''}`}            onDrop={handleDrop}            onDragOver={handleDragOver}        >            <p>{status} hero</p>            {                items.map(item => (                    status === item.status                    && <CardItem                        data={item}                        key={item.id}                        handleDragging={handleDragging}                    />                ))            }        </div>    )}

El resultado final debera verse de esta manera !

App demo gif

Opcional. Refactorizacin del cdigo en DragAndDrop.tsx

Tenemos bastante lgica en nuestro componente, por lo cual seria una buena opcin crear un custom hook para administrar esa lgica.

Creamos una carpeta de src/hooks y dentro un archivo llamado useDragAndDrop.ts

Primero definimos la funcin, la cual recibir un estado inicial que sera de tipo arreglo de Data

export const useDragAndDrop = (initialState: Data[]) => {}

Del componente DragAndDrop.tsx recortamos toda la lgica y la colocamos en el custom hook.

El valor inicial del estado de listItems sera que nos pasen por parmetro del hook.

Y por ultimo retornamos como un objeto:

  • isDragging.
  • listItems.
  • handleUpdateList.
  • handleDragging.
import { useState } from "react"import { Data, Status } from "../interfaces"export const useDragAndDrop = (initialState: Data[]) => {    const [isDragging, setIsDragging] = useState(false)    const [listItems, setListItems] = useState<Data[]>(initialState)    const handleUpdateList = (id: number, status: Status) => {       let card = listItems.find(item => item.id === id)       if (card && card.status !== status) {           card.status = status           setListItems( prev => ([                card!,                ...prev.filter(item => item.id !== id)            ]))       }   }    const handleDragging = (dragging: boolean) => setIsDragging(dragging)    return {        isDragging,        listItems,        handleUpdateList,        handleDragging,    }}

Ahora en el componente src/components/DragAndDrop.tsx llamamos a nuestro custom hook.

Le mandamos la data a nuestro hook, por parmetro y solo desestructuramos las propiedades y listo!.

import { ContainerCards } from "./ContainerCards"import { useDragAndDrop } from "../hooks/useDragAndDrop"import { Status } from "../interfaces"import { data } from "../assets"const typesHero: Status[] = ['good', 'normal', 'bad']export const DragAndDrop = () => {    const { isDragging, listItems, handleDragging, handleUpdateList } = useDragAndDrop(data)    return (        <div className="grid">            {                typesHero.map(container => (                    <ContainerCards                        items={listItems}                        status={container}                        key={container}                        isDragging={isDragging}                        handleDragging={handleDragging}                        handleUpdateList={handleUpdateList}                    />                ))            }        </div>    )}

As quedara mas legible tu componente.

Conclusin.

Este proceso es una de las formas de construir una aplicacin con funcionalidad de Drag & Drop sin usar libreras externas.

  • Una forma de mejorar esta aplicacin seria usando un administrador de estado para evitar estar pasando demasiadas props a los componentes.

  • Si quieres algo mas elaborado y expandir las funcionalidades, puedes optar por un paquete de terceros que te recomiendo bastante, y es react-beautiful-dnd, una librera muy buena y popular.

Espero haberte ayudado a entender como realizar este ejercicio,muchas gracias por llegar hasta aqu!

Te invito a que comentes si es que este articulo te resulta til o interesante, o si es que conoces alguna otra forma distinta o mejor de como hacer un drag & drop.

Demostracin en vivo.

https://drag-and-drop-react-app.netlify.app

Cdigo fuente.

GitHub logo Franklin361 / drag-and-drop-react

Creating an application using Drag & Drop with React JS

Creating an app using Drag and Drop with React without libraries !

This time, we are going to implement the functionality to do a Drag & Drop with React JS and without any other external package or library!

App demo gif

Features

  1. Card dragging.
  2. Dropping cards into a container.
  3. Sorting cards.

Technologies

  • React JS
  • TypeScript
  • Vite JS
  • Vanilla CSS 3

Installation

  1. Clone the repository (you need to have Git installed).
    git clone https://github.com/Franklin361/drag-and-drop-react
  1. Install dependencies of the project.
    npm install
  1. Run the project.
    npm run dev

Links

Demo of the application

Here's the link to the tutorial in case you'd like to take a look at it! eyes


Original Link: https://dev.to/franklin030601/creando-un-app-que-usa-drag-and-drop-con-react-sin-librerias--gm3

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To