프로젝트/Task 어플리케이션

1120 드래그 앤 드롭 기능 만들기

thinktank911 2025. 11. 20. 18:06

드래그 앤 드롭 기능 만들기

DragDropContext

Droppable

Draggable 셋팅

// App.tsx
<DragDropContext onDragEnd={handleDragEnd}>
  <LIstsContainer lists={lists} boardId={getActiveBoard.boardId} />
</DragDropContext>

// LIstsContainer -> List.tsx
<Droppable droppableId={list.listId}>
  {provided => (
    <div
      className={listWrapper}
      ref={provided.innerRef}
      {...provided.droppableProps}
    >
      <div className={header}>
        <div className={name}>{list.listName}</div>
        <GrSubtract 
          className={deleteButton}
          onClick={()=> handleListDelete(list.listId)}
        />
      </div>
      {list.tasks.map((task, index) => (
        <div
          onClick={() => handleTaskChange(boardId, list.listId, task)}
          key={task.taskId}
        >
          <Task 
            index={index}
            id={task.taskId}
            boardId={boardId}
            taskName={task.taskName}
            taskDescription={task.taskDescription}
          />
        </div>
      ))}
    {provided.placeholder}
    <ActionButton 
      boardId={boardId} 
      listId={list.listId}
    />
  </div>
  )}
</Droppable>

// Task.tsx
<Draggable draggableId={id} index={index}>
  {(provided) => (
    <div 
      className={container}
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
    >
      <div className={title}>{taskName}</div>
      <div className={description}>{taskDescription}</div>
    </div>
  )}
</Draggable>

 

onDragEnd 함수 생성

const handleDragEnd = (result: any) => {
    console.log(result);
    const { destination, source, draggableId } = result;
    console.log('lists', lists);
    const sourceList = lists.filter(list => list.listId === source.droppableId)[0];
    console.log('sourceList', sourceList);
    // const destinationList = lists.filter(list => list.listId === destination.droppableId)[0];
    // if (!result.destination) return;
    dispatch(
      sort({
        boardIndex: boards.findIndex(board => board.boardId === activeBoardId),
        droppableIdStart: source.droppableId,
        droppableIdEnd: destination.droppableId,
        droppableIndexStart: source.index,
        droppableIndexEnd: destination.index,
        draggableId
      })
    )

 

sort 로직 생성하기

boardsSlice.ts

sort: (state, {payload} : PayloadAction<TSortAction>) => {
    // same list
    if (payload.droppableIdStart === payload.droppableIdEnd) {
        const list = state.boardArray[payload.boardIndex]
                            .lists.find(
                                list => list.listId === payload.droppableIdStart
                            );

        // 변경시키는 아이템 배열에서 지워준다.
        // return 값으로 지워진 아이템 잡아준다.
        const card = list?.tasks.splice(payload.droppableIndexStart, 1);

        // card! : undefined는 없다.
        list?.tasks.splice(payload.droppableIndexEnd, 0, ...card!);               
    }
    // other list
    if (payload.droppableIdStart !== payload.droppableIdEnd) {
        const listStart = state.boardArray[payload.boardIndex].lists.find(
            list => list.listId === payload.droppableIdStart
        );

        const card = listStart?.tasks.splice(payload.droppableIndexStart, 1);
        const listEnd = state.boardArray[payload.boardIndex].lists.find(
            list => list.listId === payload.droppableIdEnd
        );

        listEnd?.tasks.splice(payload.droppableIndexEnd, 0, ...card!);

    }
}