[javascript] Beautiful Dnd의 드래그 앤 드롭 취소 및 복구 기능 구현하기

이번 블로그 포스트에서는 React 라이브러리인 Beautiful Dnd를 사용하여 드래그 앤 드롭 취소 및 복구 기능을 구현하는 방법에 대해 알아보겠습니다.

1. Beautiful Dnd 설치하기

먼저 Beautiful Dnd를 설치해야 합니다. 다음 명령어를 사용하여 패키지를 설치하세요:

npm install react-beautiful-dnd

2. 드래그 앤 드롭 컴포넌트 만들기

다음으로, 드래그 앤 드롭 컴포넌트를 만들어야 합니다. 이 컴포넌트는 Beautiful Dnd의 DragDropContext, Droppable, Draggable 컴포넌트를 사용하여 구성됩니다.

import React, { useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const DragAndDropComponent = () => {
  const [items, setItems] = useState([
    { id: 'item-1', content: 'Item 1' },
    { id: 'item-2', content: 'Item 2' },
    { id: 'item-3', content: 'Item 3' },
  ]);

  const onDragEnd = (result) => {
    if (!result.destination) {
      // 드롭이 취소되었을 경우, 아무 동작도 하지 않음
      return;
    }

    const { source, destination } = result;

    if (source.droppableId === destination.droppableId) {
      // 같은 리스트 내에서의 이동일 경우
      const newItems = [...items];
      const [movedItem] = newItems.splice(source.index, 1);
      newItems.splice(destination.index, 0, movedItem);

      setItems(newItems);
    } else {
      // 다른 리스트로 이동한 경우
      const sourceList = [...items];
      const destinationList = [...items];

      const [movedItem] = sourceList.splice(source.index, 1);
      destinationList.splice(destination.index, 0, movedItem);

      setItems(destinationList);
    }
  };

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="items">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {items.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    ref={provided.innerRef}
                    className="item"
                  >
                    {item.content}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

export default DragAndDropComponent;

3. 드래그 앤 드롭 취소 및 복구 기능 추가하기

드래그 앤 드롭 취소 및 복구 기능을 구현하기 위해선 useReducer를 사용하여 이전 상태를 관리해야 합니다. 아래와 같이 코드를 수정하세요:

import React, { useState, useReducer } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const initialState = [
  { id: 'item-1', content: 'Item 1' },
  { id: 'item-2', content: 'Item 2' },
  { id: 'item-3', content: 'Item 3' },
];

const reducer = (state, action) => {
  switch (action.type) {
    case 'SET_ITEMS':
      return action.payload;
    case 'UNDO':
      // 이전 상태로 되돌리기
      return action.payload;
    default:
      return state;
  }
};

const DragAndDropComponent = () => {
  const [items, dispatch] = useReducer(reducer, initialState);
  const [prevItems, setPrevItems] = useState([]);

  const onDragEnd = (result) => {
    if (!result.destination) {
      // 드롭이 취소되었을 경우, 아무 동작도 하지 않음
      return;
    }

    const { source, destination } = result;

    if (source.droppableId === destination.droppableId) {
      // 같은 리스트 내에서의 이동일 경우
      const newItems = [...items];
      const [movedItem] = newItems.splice(source.index, 1);
      newItems.splice(destination.index, 0, movedItem);

      dispatch({ type: 'SET_ITEMS', payload: newItems });
      setPrevItems([...items]); // 이전 상태 저장
    } else {
      // 다른 리스트로 이동한 경우
      const sourceList = [...items];
      const destinationList = [...items];

      const [movedItem] = sourceList.splice(source.index, 1);
      destinationList.splice(destination.index, 0, movedItem);

      dispatch({ type: 'SET_ITEMS', payload: destinationList });
      setPrevItems([...items]); // 이전 상태 저장
    }
  };

  const undo = () => {
    dispatch({ type: 'UNDO', payload: prevItems });
  };

  return (
    <>
      <DragDropContext onDragEnd={onDragEnd}>
        <Droppable droppableId="items">
          {(provided) => (
            <div {...provided.droppableProps} ref={provided.innerRef}>
              {items.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index={index}>
                  {(provided) => (
                    <div
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      ref={provided.innerRef}
                      className="item"
                    >
                      {item.content}
                    </div>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
      <button onClick={undo}>Undo</button>
    </>
  );
};

export default DragAndDropComponent;

드래그 앤 드롭 취소 및 복구 기능을 구현하고 싶은 경우 위와 같은 방법으로 코드를 수정하면 됩니다.

이제 Beautiful Dnd를 사용하여 드래그 앤 드롭 취소 및 복구 기능을 구현하기 위한 기본적인 방법을 알게 되었습니다. 자세한 내용은 Beautiful Dnd 공식 문서를 참고하시기 바랍니다.

REFERENCES