Build a simple drag and drop list with React

Drag and drop list React

Let's suppose that you want to create a simple drag and drop list in React.

The first step is to define a list (fruits in this example 🍍), and render it as draggable.

Then, define 3 functions: start(), over() and end():

jsx
import React, { useState } from 'react';

const DragAndDrop = () => {

    const [list,    setList]    = useState(['Banana', 'Apple', 'Kiwi', 'Mango']);
    const [dragged, setDragged] = useState(null);

    const start = (e) => { /* Activates when user starts dragging */ }

    const over = (e) => { /* Activates while user is dragging */ }

    const end = () => { /* Activates when user finishes dragging */ }

    return(
        <div className = 'List'>
            {list.map((fruit, i) => 
                <div key = {i} id = {i} onDragStart = {start} onDragEnd = {end} onDragOver = {over} draggable>{fruit}</div>
            )}
        </div>
    );
    
}

export default DragAndDrop;

Start dragging

Save the id of the component on drag start:

jsx
const start = (e) => {

    setDragged(e.target.id);

}

End dragging

Reset the variable on drag end:

jsx
const end = () => {

    setDragged(null);

}

While dragging

You'll need to move the fruit in the array of fruits and update the list accordingly while the user is dragging the element:

jsx
const over = (e) => {

    let newPosition = parseInt(e.target.id);

    if(newPosition >= 0){

        let copy = [...list];

        let moveFruit = ((from, to, fruit) => {

            copy.splice(from, 1);
            copy.splice(to, 0, fruit);

        })(dragged, newPosition, list[dragged]);

        setList(copy);
        setDragged(newPosition);

    }

}

Important: notice how you need to setDragged(newPosition), as the fruit (dragged element) will change its position on the go.

Final result

Here is the final result:

jsx
import React, { useState } from 'react';

const DragAndDrop = () => {

    const [list,    setList]    = useState(['Banana', 'Apple', 'Kiwi', 'Mango']);
    const [dragged, setDragged] = useState(null);

    const start = (e) => {

        setDragged(e.target.id);

    }

    const over = (e) => {

        let newPosition = parseInt(e.target.id);

        if(newPosition >= 0){

            let copy = [...list];

            let moveFruit = ((from, to, fruit) => {

                copy.splice(from, 1);
                copy.splice(to, 0, fruit);

            })(dragged, newPosition, list[dragged]);

            setList(copy);
            setDragged(newPosition);

        }

    }

    const end = () => {

        setDragged(null);

    }

    return(
        <div className = 'List'>
            {list.map((fruit, i) => 
                <div key = {i} id = {i} onDragStart = {start} onDragEnd = {end} onDragOver = {over} draggable>{fruit}</div>
            )}
        </div>
    );
    
}

export default DragAndDrop;

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.