처음 구현하는 기능은 언제나 떨리고 조금 설렌다🤓
프론트엔드에서 흔하게 접할 수 있는 Drag and Drop 기능과 새로 정렬된 리스트의 순서를 서버에 바로 반영해 새로고침해도 정렬이 유지되는 기능 구현해보자!
내가 사용한 라이브러리는 react-sortablejs이다.
npm i react-sortablejs
깃헙 공식 문서에 나와있는 기본형은 아래와 같다.
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라는 콜백 함수를 지정해주었다.
const handleDragEnd = (event) => {
const updatedList = [...list];
const movedItem = updatedList.splice(event.oldIndex, 1);
updatedList.splice(event.newIndex, 0, movedItem);
setList(updatedList);
};
SortableEvent 객체의 주요 속성은 다음과 같다.
새로 정렬된 리스트를 서버에 반영하면 새로고침해도 정렬된 리스트가 유지된다!