Sortablejs를 이용한 Drag and Drop 구현

0
post-custom-banner

처음 구현하는 기능은 언제나 떨리고 조금 설렌다🤓

프론트엔드에서 흔하게 접할 수 있는 Drag and Drop 기능과 새로 정렬된 리스트의 순서를 서버에 바로 반영해 새로고침해도 정렬이 유지되는 기능 구현해보자!

내가 사용한 라이브러리는 react-sortablejs이다.


1️⃣ 설치

npm i react-sortablejs

2️⃣ Drag and Drop 구현

깃헙 공식 문서에 나와있는 기본형은 아래와 같다.

import React, { FC, useState } from "react";
import { ReactSortable } from "react-sortablejs";

interface ItemType {
  id: number;
  name: string;
}

export const BasicFunction: FC = (props) => {
  const [state, setState] = useState<ItemType[]>([
    { id: 1, name: "shrek" },
    { id: 2, name: "fiona" },
  ]);

  return (
    <ReactSortable list={state} setList={setState}>
      {state.map((item) => (
        <div key={item.id}>{item.name}</div>
      ))}
    </ReactSortable>
  );
};

오 생각보다 단순하다..!

import { ReactSortable } from "react-sortablejs";
const [list, setList] = useState(lists);

<ReactSortable tag={"ul"} animation={100} list={list.map((item) => ({ ...item, id: item.tid }))} setList={setList} className="flex list-none flex-col gap-[20px]" onEnd={handleDragEnd}>
            {list?.map((item, index) => (
                <TopicList
                    index={index}
                />
            ))}
</ReactSortable>

전체 리스트 목록을 ReactSortable 컴포넌트로 감싸고 필요한 속성 값을 지정해주면 끝!

다양한 옵션을 제공하는데 그 중 사용한 것에 대해 간략히 정리를 하자면

  • tag
    ReactSortable 컴포넌트가 어떤 HTML 태그나 컴포넌트로 렌더링될지를 지정하는 속성이다. 나는 TopicList가 li태그이기 때문에 ul로 지정해주었다.

  • animation
    항목을 정렬할 때 이동하는 애니메이션의 속도를 밀리초(ms) 단위로 설정.
    만약 animation={0}으로 설정하면 애니메이션 없이 즉시 이동된다.

  • list
    ReactSortable에서 사용할 항목 배열로 필수로 지정해주어야 하는 속성이다.

  • setList
    항목 목록의 상태를 설정하는 함수로 정렬된 후의 새로운 상태를 받아 컴포넌트의 상태를 업데이트해준다. list와 마찬가지로 필수로 지정해주어야 한다.

  • onEnd
    onEnd?: ((evt: Sortable.SortableEvent, sortable: Sortable | null, store: Store) => void)

    ReactSortable 컴포넌트에서 드래그 앤 드롭 작업이 끝났을 때 호출되는 콜백 함수를 지정하고자 할 때 사용하는 속성이다. 이 콜백 함수는 SortableEvent 객체를 매개변수로 받아 드래그된 항목과 그 위치 변경에 대한 정보를 제공한다.

    나는 드래그가 끝나고 변경된 위치를 서버에 반영해 새로고침해도 정렬이 유지되도록 구현하고 싶었기 때문에 handleDragEnd라는 콜백 함수를 지정해주었다.



3️⃣ 정렬 구현

const handleDragEnd = (event) => {
    const updatedList = [...list];
    const movedItem = updatedList.splice(event.oldIndex, 1);
    updatedList.splice(event.newIndex, 0, movedItem);
    setList(updatedList);
};

SortableEvent 객체의 주요 속성은 다음과 같다.

  • item : 드래그된 DOM 요소
  • from : 드래그 시작 위치의 DOM 요소
  • to : 드롭된 위치의 DOM 요소
  • oldIndex : 드래그 시작 전의 요소 인덱스
  • newIndex : 드래그 후의 요소 인덱스
  1. 먼저 리스트 배열의 복사본을 만들고
  2. 복사본을 splice메소드를 사용해 oldIndex 속성으로 드래그 한 요소를 제거한다.
  3. 복사본을 다시 splice 메소드로 드래그한 후 인덱스 위치에 제거한 요소를 삽입한 후 setList로 상태를 업데이트 해준다.


4️⃣ 최종

새로 정렬된 리스트를 서버에 반영하면 새로고침해도 정렬된 리스트가 유지된다!



🧷 참고

post-custom-banner

0개의 댓글