Skip to content

Drag and Drop Board

Move tasks between columns with the native HTML drag and drop events, tracking the dragged item in a ref.

Stage 4core2 min read

Problem Statement

Build a small kanban board with Todo, In Progress, and Completed columns where tasks can be dragged from one column to another.

Functional Requirements

  1. Columns: Render one column per key in the initialData prop, with its tasks listed under the column title.
  2. Drag a task: Every task is draggable, and the dragged task fades to 50% opacity until the drag ends.
  3. Drop on a column: Dropping a task on a column removes it from its source column and adds it to the end of the target column.
  4. Ignore other drops: Dropping something that is not a task, like a file or selected text, changes nothing.

Technical Constraints

  • Use the native HTML drag and drop events (dragstart, dragend, dragover, drop). No library.
  • Track the dragged task and its source column in refs, and update the board with an immutable setData.

Component Overview

This is a React component implementing drag and drop functionality, typically used for kanban boards or task management interfaces.

Key Concepts

State and Refs

const [data, setData] = useState(initialData);
const dragItem = useRef();
const dragContainer = useRef();
  • data: Stores the current state of items in different containers
  • dragItem: Ref to track the item being dragged
  • dragContainer: Ref to track the source container of dragged item

Event Handlers

1. handleDragStart

const handleDragStart = (e, item, container) => {
  dragItem.current = item;
  dragContainer.current = container;
  e.target.style.opacity = 0.5;
};
  • Triggered when user starts dragging an item
  • Stores the dragged item and its container in refs
  • Reduces opacity of dragged element for visual feedback

2. handleDragEnd

const handleDragEnd = (e) => {
  e.target.style.opacity = 1;
  dragItem.current = null;
  dragContainer.current = null;
};
  • Triggered when drag operation ends
  • Restores opacity of dragged element
  • Clears the refs so an old drag cannot be replayed by a later drop

3. handleDrop

const handleDrop = (e, targetContainer) => {
  const item = dragItem.current;
  const sourceContainer = dragContainer.current;
  // Ignore drops that did not start on one of our tasks (files, text)
  if (!item) return;
  dragItem.current = null;
  dragContainer.current = null;
  setData((prev) => {
    const newData = { ...prev };
    // Remove item from source container
    newData[sourceContainer] = newData[sourceContainer].filter(
      (i) => i !== item
    );
    // Add item to target container
    newData[targetContainer] = [...newData[targetContainer], item];
    return newData;
  });
};
  • Handles the drop event
  • Does nothing if no task drag is in progress
  • Moves item from source to target container
  • Updates state with new arrangement

4. handleDragOver

const handleDragOver = (e) => {
  e.preventDefault();
};
  • Required to enable dropping
  • Prevents default browser behavior

Render Logic

Container Structure

<div className="board">
  {Object.keys(data).map((container, index) => (
    <div
      key={index}
      className="column"
      onDrop={(e) => handleDrop(e, container)}
      onDragOver={handleDragOver}
    >
  • Maps through containers
  • Sets up drop zone for each container

Draggable Items

<div
  key={idx}
  className="task"
  draggable
  onDragStart={(e) => handleDragStart(e, item, container)}
  onDragEnd={(e) => handleDragEnd(e)}
>
  {item}
</div>
  • Renders individual draggable items
  • Attaches drag event handlers

Focus Points

  1. HTML5 Drag and Drop API

    • Native browser API
    • Key events: dragstart, dragend, dragover, drop
  2. React State Management

    • Immutable state updates
    • Using spread operator for object/array manipulation
  3. React Refs

    • Purpose of useRef
    • Maintaining values between renders
  4. Event Handling

    • preventDefault() usage
    • Event parameter in handlers

In this topic

Done with this topic?

How well do you know it?

PreviousLite Excel Sheet