📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄
구현하고자 하는 기능
구현 방법
라이브러리 설치하기
npm install react-beautiful-dnd --save
우선 라이브러리를 사용하려면 다음과 같은 명령어를 입력해서 설치부터 해준다.
여담으로, 뒤에 --save를 하는 이유는 패키지를 설치할 때 해당 패키지를 프로젝트의 'package.json' 파일에 의존성으로 추가하도록 지시하기 위함이다. 의존성으로 추가된 패키지 정보는 'dependencies' 항목에 기록되며, 이렇게 정의된 패키지는 나중에 'npm install' 명령을 통해 프로젝트를 복원할 때 자동으로 설치된다.
기본 구조
<DragDropContext>
<Droppable>
<Draggble>List</Draggble>
<Draggble>List</Draggble>
<Draggble>List</Draggble>
</Droppable>
</DragDropContext>
대략적인 구조는 다음과 같다. 가장 바깥에서 드래그 앤 드롭을 사용할 영역을 <DragDropContext>로 크게 감싸준다.
다음으로는 <Droppable>로 드래그 앤 드롭을 사용할 리스트들을 감싸준다. 마지막으로, 드래그 앤 드롭 기능을
넣어줄 요소들을 <Draggble>로 감싸주면 된다. 일단 기본적인 구조는 이렇다.
기능 구현하기
<DragDropContext onDragEnd={handleEnd}>
<Droppable droppableId="todo">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{todoData.map((data, index) => (
<Draggble
key={data.id}
draggableId={data.id.toString()}
index={index}
>
{(provided, snapshot) => (
<div key={data.id}
{...provided.draggableProps}
ref={provided.innerRef}
className={`${snapshot.isDragging ? "bg-fff" : "bg-fff"}`}
>
...contents
</div>
)}
</Draggble>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
드래그 앤 드롭 기능을 구현한 전체적인 코드는 위와 같다.
1) <Droppable> 영역 구현하기
우선, Droppable의 id 값을 설정해 준다. 현재 구현하고자 하는 앱은 todoList이므로, "todo"라고 해주었다.
Droppable 안에 provided라는 인자를 받아서 <Draggble> 전체를 감싸주었다.
드래그 앤 드롭 기능이 구현될 전체 요소들을 감싸주는 <div> 요소를 하나 만들고, 그 안에 provided.droppableProps를
전달해 주고, ref로는 provided.innerRef를 설정해 준다.
2) <Draggable> 영역 구현하기
Droppable과 똑같이 id값을 설정해 준다. map()으로 반복되는 요소이므로 key값을 넣어주었고, 순서를 위한 index 값도
넣어주었다. provided와 snapshot 인자를 받아서 드래그 앤 드롭 기능을 수행할 때의 이벤트 동작에 대한 정보들을
provided.draggbleProps로 전달해 주고 마찬가지로 ref를 설정해 주었다.
snapshot.isDragging은 현재 드래그된 상태인가를 반환해 주는 값으로 위 코드의 경우에는 드래그가 된 상태와 드롭된 상태 모두 흰 배경으로 하고 싶어서 같은 클래스 이름을 설정해 주었다. (드래그됐을 때 : 드롭됐을 때)
여기서 주의할 점은 Draggble 요소 자체에 배경색을 주면 안 된다는 점이다. 배경색을 주면 드래그를 했을 때도 그 자리에 배경색이 그대로 남아 있어서 드래그되는 요소를 가리게 된다. 따라서, snapshot을 통해 드래그됐을 때와 드롭됐을 때의 배경색을 각각 설정해주어야 한다.
3) provided.placeholder
드래그 앤 드롭 기능의 부자연스러움을 없애주기 위해 필수로 추가해 준다.
const [todoData, setTodoData] = useState([]);
const handleEnd = (result) => {
if (!result.destination) return;
const newTodoData = [...todoData];
// 변경시키는 아이템을 배열에서 삭제하고, return 값으로 지워진 아이템을 잡아준다.
const [reorderedItem] = newTodoData.splice(result.source.index, 1);
// 원하는 자리에 reorderedItem을 삽입해준다.
newTodoData.splice(result.destination.index, 0, reorderedItem);
setTodoData(newTodoData);
}
4) <DragDropContext>에 onDragEnd로 함수 전달하기
1~3까지가 겉으로 보이는 드래그 앤 드롭의 효과만을 구현한 것이라면, 이번에는 실제로 드래그 앤 드롭을 했을 때
데이터의 순서가 바뀌는 것을 구현하는 단계이다.
handleEnd 함수는 result를 인자로 받고 제자리일 때는 return, 자리를 이동했을 때는 reorderedItem 변수에 이동한 자리의 아이템 값을 할당해 준다. 그 후 splice() 메소드를 이용해서 원하는 자리에 reorderedItem를 삽입해 준다.
즉, 드래그 한 아이템을 배열에서 삭제 => 드롭한 자리에 다시 삽입하는 것이다.
1. <DragDropContext> 안에 <Droppable> 안에 <Droggable>
2. <Droppable>과 <Droggable>은 각각 안에 provided Props를 전달해 주고, ref를 설정해 준다.
3. <Draggable>의 마지막 형제 요소로 {provided.placeholder}는 필수!
4. 드롭했을 때의 기능은 <DragDropContext>의 onDragEnd에 함수로 전달하기
'React' 카테고리의 다른 글
[React] 백엔드 서버와 통신할 수 있는 Axios 사용해보기 (0) | 2023.06.24 |
---|---|
[React] useState 상태변화 함수의 매개변수로 기존 값 가져오기 (0) | 2023.06.20 |
[React] 가상 돔(Virtual DOM)이란? (0) | 2023.04.24 |
[React] 컴포넌트 export 하는 방법 (default, named) (0) | 2023.04.15 |
[React] 성능 최적화 : useMemo, useCallback, React.memo (0) | 2023.03.17 |