React JS Custom Draggable Component with Sorting without any Draggable library
Categories - React Js Tags - React Js JavaScript   Maniruzzaman Akash   2 years ago   2481   3 minutes   0

React JS Custom Draggable Component with Sorting without any Draggable library

Draggable Component in React JS is very basic and important thing for almost any of the applications nowadays. And sorting is also important for any of the practical example projects. So, Let’s make our own custom Draggable Component with Sorting support.

Requirements

  1. TypeScript
  2. React
  3. React-JSX

Live Demo Before start

Step by step documentation:

Draggable Component

type Props = {
  /**
   * Drag ID.
   */
  id: string;

  /**
   * Dragged Children.
   */
  children: React.ReactNode;

  /**
   * Dragging item.
   */
  item?: object;

  /**
   * On drag start for the dragging element.
   */
  onDragStart?: (event, item) => void;

  /**
   * On drop dragging element.
   */
  onDrop?: (event, item) => void;
};

export default function Draggable({
  children,
  id,
  item = {},
  onDragStart = (event, item) => {},
  onDrop = (event, item) => {}
}: Props) {
  const handleDrag = (ev) => {
    onDragStart(ev, item);
  };

  const handleDrop = (ev) => {
    onDrop(ev, item);
  };

  return (
    <div
      draggable={true}
      id={id}
      onDragOver={(ev) => ev.preventDefault()}
      onDragStart={handleDrag}
      onDrop={handleDrop}
      className="animation-move"
    >
      {children}
    </div>
  );
} 

Sortable List Component

Make a Sortable component so that we can pass our items to there which needs to be sorted.

Inside SortableList.tsx file -

import { useState } from "react";
import { arrayMove } from "./array-move";
import Draggable from "./Draggable";

export interface DraggableItem {
  id: string | number;
}

export interface DraggableItems {
  items: Array<DraggableItem | any>;

  setItems: () => void;

  children?: React.ReactNode;

  component: (item: any) => JSX.Element;
}

const SortableList = ({ items, setItems, component }: DraggableItems) => {
  const [dragId, setDragId] = useState("");

  const onDrop = (ev, item) => {
    let currentPos = 0,
      droppedPos = 0;

    for (let i = 0; i < items.length; i++) {
      if (dragId == items[i].id) {
        currentPos = i;
      }

      if (ev.currentTarget.id == items[i].id) {
        droppedPos = i;
      }
    }

    const newItems = arrayMove([...items], currentPos, droppedPos);
    setItems(newItems);
  };

  const onDragStart = (ev, item) => {
    setDragId(item.id);
  };

  const renderComponent = (componentJsx, item, index) => {
    const Component = componentJsx;

    return <Component item={item} index={index} />;
  };

  return (
    <>
      {items.map((item, index) => (
        <Draggable
          key={index}
          id={item.id}
          onDrop={onDrop}
          onDragStart={onDragStart}
          item={item}
        >
          {renderComponent(component, item, index)}
        </Draggable>
      ))}
    </>
  );
};

export default SortableList;

ArrayMove Method

Inside array-move.ts file -

/**
 * Move an array to different position.
 *
 * @param  arr
 * @param  oldIndex
 * @param  newIndex
 */
export function arrayMove(arr: Array<any>, oldIndex: number, newIndex: number) {
  if (newIndex >= arr.length) {
    let k = newIndex - arr.length + 1;
    while (k--) {
      arr.push(undefined);
    }
  }

  arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);

  return arr;
}

Final App.ts file from where Call the SortableList Component

import "./styles.css";
import SortableList from "./SortableList";
import { useState } from "react";

export default function App() {
  const [items, setItems] = useState([
    {
      name: "Item 1",
      id: 1
    },
    {
      name: "Item 2",
      id: 2
    },
    {
      name: "Item 3",
      id: 3
    }
  ]);

  const DragComponent = ({ item, index }) => {
    return (
      <div className="animation-move" style={{ border: "1px dotted #ccc" }}>
        <h2>{item.name}</h2>
        <p>Index - {index}</p>
      </div>
    );
  };

  return (
    <div className="App">
      <h1>React Draggable Sorting</h1>

      <SortableList
        items={items}
        setItems={setItems}
        component={DragComponent}
      />
    </div>
  );
}

We’ve used a little bit of style -

Inside styles.css

.App {
  font-family: sans-serif;
  text-align: center;
}

.animation-move {
  cursor: move;
  animation: moveAnimation 3.5s infinite;
}

@keyframes moveAnimation {
  0%,
  100% {
    top: 5px;
  }
  50% {
    top: 0px;
  }
}

**Code Sandbox Link ** https://codesandbox.io/s/react-draggable-with-sorting-71w4l8?file=/src/App.tsx

Please add your comments if you faced any problem or just check live Sandbox URL.

Previous
PHP If-else-elseif and Switch-case
Next
PHP String Functions - All necessary String functions in PHP to manage strings better.