Open In App

Drag and Drop Sortable List Using ReactJS

Last Updated : 30 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we’ll create a Drag and Drop sortable list using React JS. Within this web application, users can effortlessly rearrange­ a list of items through the simple act of dragging and dropping.

Preview Image:

Drag-and-Drop-sortable-list-Using-React-JS

Prerequisites

Approach:

  • This React-based application, “Drag and Drop Sortable List,” allows users to reorder a list of items effortlessly. Users can drag and drop items within the list to change their order.
  • The constructor se­rves to initialize various aspects of the­ component’s state. These­ include the list of items, the­ currently dragged item, and input fie­lds for adding new items.
  • The me­thod handleDragStart is responsible for se­tting up the dragging item and enabling its draggable­ property. On the other hand, handle­DragEnd clears the dragging item once­ it has been rele­ased.
  • To allow item drops, handleDragOve­r comes into play. If a drop is valid, handleDrop takes care­ of rearranging the items accordingly. Additionally, both handle­NameChange and handleImage­Change update values in input fie­lds.

Steps to Create the Application:

Step 1: Create a react application by using this command

npx create-react-app  image-color-picker

Step 2: After creating your project folder, i.e. image-color-picker, use the following command to navigate to it:

cd  image-color-picker

Step 3: Install required dependences

npm install react-icons --save

Project Structure:

package.json file will look like

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
"react-icons": "^4.11.0"
}

Example: Write the below code in App.js file and App.css in the src directory

Javascript




import React, { Component } from 'react';
import './App.css';
import { RiDragMove2Line } from 'react-icons/ri';
  
class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            items: [
                {
                    id: 1,
                    name: 'Kristina Zasiadko',
                    image:
                },
                {
                    id: 2,
                    name: 'John Doe',
                    image:
                },
                {
                    id: 3,
                    name: 'Jane Smith',
                    image:
                },
                // Add more items here
            ],
            draggingItem: null,
            newItemName: '',
            newItemImage: '',
        };
    }
  
    handleDragStart = (e, item) => {
        this.setState({ draggingItem: item });
        e.dataTransfer.setData('text/plain', '');
    };
  
    handleDragEnd = () => {
        this.setState({ draggingItem: null });
    };
  
    handleDragOver = (e) => {
        e.preventDefault();
    };
  
    handleDrop = (e, targetItem) => {
        const { draggingItem, items } = this.state;
        if (!draggingItem) return;
  
        const currentIndex = items.indexOf(draggingItem);
        const targetIndex = items.indexOf(targetItem);
  
        if (currentIndex !== -1 && targetIndex !== -1) {
            items.splice(currentIndex, 1);
            items.splice(targetIndex, 0, draggingItem);
            this.setState({ items });
        }
    };
  
    handleNameChange = (e) => {
        this.setState({ newItemName: e.target.value });
    };
  
    handleImageChange = (e) => {
        this.setState({ newItemImage: e.target.value });
    };
  
    addNewItem = () => {
          
        // Generate a unique ID for the new item
        const newItemId = 
            Math.max(...this.state.items.map((item) 
                => item.id)) + 1;
        const newItem = {
            id: newItemId,
            name: this.state.newItemName,
            image: this.state.newItemImage,
        };
  
        // Add the new item to the state
        this.setState({
            items: [...this.state.items, newItem],
            newItemName: '', // Clear the input fields
            newItemImage: '',
        });
    };
  
    render() {
        return (
            <div className="sortable-list">
                <div className="new-item">
                    <input
                        type="text"
                        placeholder="Name"
                        value={this.state.newItemName}
                        onChange={this.handleNameChange}
                        className="input-field"
                    />
                    <input
                        type="text"
                        placeholder="Image URL"
                        value={this.state.newItemImage}
                        onChange={this.handleImageChange}
                        className="input-field"
                    />
                    <button onClick={this.addNewItem} 
                            className="add-button">
                        Add New Item
                    </button>
                </div>
                {this.state.items.map((item, index) => (
                    <div
                        key={item.id}
                        className=
                            {`item ${item === this.state.draggingItem ? 
                                'dragging' : ''
                            }`}
                        draggable="true"
                        onDragStart={(e) => 
                            this.handleDragStart(e, item)}
                        onDragEnd={this.handleDragEnd}
                        onDragOver={this.handleDragOver}
                        onDrop={(e) => this.handleDrop(e, item)}
                    >
                        <div className="details">
                            <img src={item.image} alt={item.name} />
                            <span>{item.name}</span>
                        </div>
                          
                        {/* Use the React icon component */}
                        <RiDragMove2Line /> 
                    </div>
                ))}
            </div>
        );
    }
}
  
export default App;


CSS




@import url(
  
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Poppins', sans-serif;
}
  
body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: #f4f4f4;
}
  
.sortable-list {
    width: 425px;
    background: #ffffff;
    border-radius: 10px;
    padding: 20px;
    box-shadow: 0 13px 46px rgba(0, 0, 0, 0.1);
}
  
.input-field {
    padding: 10px;
    margin: 8px 0;
    border: 1px solid #ccc;
    border-radius: 14px;
    font-size: 16px;
    width: 100%;
    box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1);
}
  
.add-button {
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 14px;
    padding: 10px 20px;
    cursor: pointer;
    font-size: 16px;
    width: 100%;
    transition: background-color 0.3s ease;
    box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1);
}
  
.add-button:hover {
    background-color: #0056b3;
}
  
.sortable-list .item {
    margin-top: 1rem;
    border: 1px solid #ccc;
    justify-content: space-between;
    list-style: none;
    display: flex;
    cursor: move;
    background: #ffffff;
    align-items: center;
    border-radius: 10px;
    padding: 15px;
    margin-bottom: 10px;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1);
}
  
.item .details {
    display: flex;
    align-items: center;
}
  
.item .details img {
    height: 60px;
    width: 60px;
    pointer-events: none;
    margin-right: 15px;
    object-fit: cover;
    border-radius: 50%;
}
  
.item .details span {
    font-size: 1.2rem;
    font-weight: 500;
    color: #333;
}
  
.item i {
    color: #474747;
    font-size: 1.13rem;
}
  
.item.dragging {
    opacity: 0.6;
}
  
.item.dragging .details,
.item.dragging i {
    opacity: 0.8;
    transform: scale(1.02);
    background: #f0f0f0;
}


Steps to run the Application:

  • Step 1: Type the following command in the terminal:
npm start
  • Step 2: Type the following URL in the browser:
 http://localhost:3000/

Output:Drag-and-Drop-sortable-list-Using-React-JS



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads