DnD(Drag&Drop)

장현욱(Artlogy)·2022년 12월 9일
0

React

목록 보기
23/24
post-thumbnail

React-Beautiful-dnd

프론트개발을 하다보면 드래그 드롭이 UX적으로 적합 할 때가 종종 생깁니다.
허나 결과물은 간단한데 기능을 구현하는 과정은 전혀 간단하지 않기때문에 보일러플레이트를 사용해봅시다.

설치

# npm
$ npm i -s react-beautiful-dnd

# yarn
$ yarn add react-beautiful-dnd

# typescript
npm i -s @types/react-beautiful-dnd
yarn add @types/react-beautiful-dnd

1. DragDropContext

  • 드래그앤드롭을 사용하려면 해당 범위의 React 트리를 <DragDropContext>로 래핑해야합니다.
...
//Drag가 시작되면 호출 될 함수
const onDragStart = () => {};
//Drag가 끝나면(Drop) 호출 될 함수
const onDragEnd = () => {};

  return getLayout(
    <DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
        <App />
    </DragDropContext>
  );
...

2. Dropable

이제 Drag&Drop이 적용 될 요소의 범위를 설정해줄차례입니다.
기본적으론 원하는 요소범위 만큼 <Dropable>을 래핑하면 됩니다.

<DragDropContext onDragStart={()=>{}} onDragEnd={()=>{}}>
	<Droppable droppableId="todos">
      {({ droppableProps, innerRef, placeholder }) => (
        <ul className="todos" {...droppableProps} ref={innerRef}>
          {todos.map(({ id, title }, idx) => (
            <li>{title}</li>
          ))}
          {placeholder}
        </ul>
      )}
    </Droppable>
</DragDropContext>
  • provided.draggableProps 객체는 <Draggable>의 드래그 동작에 필요한 프로퍼티들이 담겨 있습니다. provided.innerRef를 바인딩한 요소에 적용해야 합니다.

  • provided.dragHandleProps<Draggable> 전체를 드래그하기 위한 핸들입니다.

3. Dragable

이제 Drop범위안의 원하는 요소를 Drag가능하게 만들어 봅시다.

<DragDropContext onDragStart={()=>{}} onDragEnd={()=>{}}>
  <Droppable droppableId="todos">
      {({ droppableProps, innerRef, placeholder }) => (
        <ul className="todos" {...droppableProps} ref={innerRef}>
          {todos.map(({ id, title }, index) => (
            <Draggable key={id} draggableId={id} index={index}>
              {(provided) => (
                <li
                  ref={provided.innerRef}
                  {...provided.dragHandleProps}
                  {...provided.draggableProps}
                >
                  {title}
                </li>
              )}
            </Draggable>
          ))}
          {placeholder}
        </ul>
      )}
    </Droppable>
</DragDropContext>
  • <Draggable>이 정상적으로 동작하기 위해서는 draggable로 간주될 ReactElement에 provided.innerRef를 바인드 해야합니다.

  • provided.draggableProps 객체는 <Draggable>의 드래그 동작에 필요한 프로퍼티들이 담겨 있습니다.

  • provided.dragHandleProps<Draggable> 전체를 드래그하기 위한 핸들입니다.

4. 상태 저장

드롭 후 상태를 저장하고 싶다면 <DragDropContext>onDragEnd를 이용합니다.

const [loading, setLoading] = React.useState<boolean>(true);
  const [todoList, setTodoList] = React.useState(todos);
  useEffect(() => {
    setLoading(false);
  }, []);
  const handleDrop = (result: DropResult) => {
    // 목적지가 없다면 ㅂㅂ
    if (!result.destination) return;

    // 현재 리스트
    const items = [...todoList];
    // 드레그 중인 인덱스정보 반환과 동시에 리스트에서 잠시 삭제
    const [reorderedItem] = items.splice(result.source.index, 1);

    // 목적지 인덱스에 위치에 드롭한 정보를 넣는다.
    items.splice(result.destination.index, 0, reorderedItem);

    setTodoList(items);
  };
  return (
    <>
      {!loading && (
        <DragDropContext onDragEnd={handleDrop}>
          <Droppable droppableId="todos">
            {({ droppableProps, innerRef, placeholder }) => (
              <ul className="todos" {...droppableProps} ref={innerRef}>
                {todoList.map(({ id, title }, index) => (
                  <Draggable key={id} draggableId={`ddas` + id} index={index}>
                    {(provided) => (
                      <li
                        ref={provided.innerRef}
                        {...provided.dragHandleProps}
                        {...provided.draggableProps}
                      >
                        {title}
                      </li>
                    )}
                  </Draggable>
                ))}
                {placeholder}
              </ul>
            )}
          </Droppable>
        </DragDropContext>
      )}
    </>
  );

0개의 댓글