[React] Drag and Drop (feat. react-beautiful-dnd)

camille·2022년 11월 28일
1
post-thumbnail

Install

Atlassian에서 만든 React DND 라이브러리 react-beautiful-dnd를 사용해 안전하게 dnd를 구현해보자.

npm add react-beautiful-dnd  
npm add -D @types/react-beautiful-dnd

타입스크립트를 사용한다면 위의 방식 두가지를 통해서 설치를 해준다.

📕 공식 문서 : https://github.com/atlassian/react-beautiful-dnd

✅ React18에서는 아직 잘 호환되지 않기 때문에 strictMode를 꺼서 사용하라고 권장하고 있다.

따라서 index.js에서 strict모드를 지워주도록 하자!

삭제 전

 ReactDOM.render(
   <React.StrictMode>
     <App />
   </React.StrictMode>,

   document.getElementById('root')
 );
삭제 후

 ReactDOM.render(
     <App />
   document.getElementById('root')
 );

import

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

DragDropContext

const DndContainer = ({ item, setItem }: any) => {

  return (
    <DragDropContext>
      <Droppable droppableId="lists">
        {provided => (
          <div className="lists" {...provided.droppableProps} ref={provided.innerRef}>
           // 여기에 움직일 컴포넌트를 넣어준다.
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

export default DndContainer;

DragDropContext를 통해서 ContextAPI의 Provider 처럼 DND의 상태를 제공해주는 역할을 한다고 보면 될 것같다. 이 안에서 onDragEnd 등 다양한 DND 이벤트를 등록해준다.

Droppable

Drop할 수 있는 영역으로 명시한다.

Draggable

Drag할 수 있는 영역으로 컴포넌트를 감싸준다.

droppableId

✔️ 드롭 가능한 영역을 구분할 id를 표시한다. ex) todo, doing, done

provided

<Droppable droppableId="droppable-1">
  {(provided, snapshot) => (
    <div ref={provided.innerRef} {...provided.droppableProps}>
      Good to go
      {provided.placeholder}
    </div>
  )}
</Droppable>

✔️ provided.innerRef 라이브러리에서 컴포넌트 DOM을 조작하기 위해서 필수로 등록해 줘야한다.

✔️ provided.droppableProps

  • 우리가 전달한 props를 라이브러리에서 사용할 수 있는 형태로 DOM data에 등록시켜주는 역할을 한다.
<div data-rbd-droppable-id="droppable" data-rbd-droppable-context-id="1">

✔️ provided.placeholder

  • drop 될 때 공간을 만들기 위해서 필요하다.

snapshot

  • snapshot.isDraggingOver
    이름 그대로, 이를 통해서 아이템을 올려놀 수 있을 때 스타일을 추가할 수 있다.
  {(provided, snapshot) => (
    <div 
        ref={provided.innerRef}
        {...provided.droppableProps}
        style={{ background: snapshot.isDraggingOver ? 'pink' : 'gray' }}
    >
      {...}
      {provided.placeholder}
    </div>
  )}
{items.map((item, index) => (
  <Draggable key={item.id} draggableId={item.id} index={index}>
    {(provided, snapshot) => (
      <div
        ref={provided.innerRef}
        {...provided.draggableProps}
        {...provided.dragHandleProps}
        >
        {item.content}
      </div>
    )}
  </Draggable>
))}

👩‍🏫 체크리스트

  1. 각 컴포넌트에 유익한 id를 지정해줘야 한다.
  2. key와 droppableId, draggableId는 같아야한다!!
  3. Droppable의 provided와 Draggable의 provided는 다른 역할임을 유의해야한다.

0개의 댓글