React Drag&Drop 끌어오는 장바구니 만들기

수정·2024년 2월 5일
0

React

목록 보기
10/14
post-thumbnail

오늘은 Drag and Drop 기능을 만들었던 것에 정리해볼 예정이다.

Drag and Drop을 손쉽게 구현할 수 있는 react-dnd 라이브러리도 있지만,
나는 이번에 간단한 드래그 앤 드롭을 구현할 것이기 때문에 직접 구현하는 것을 선택했다!

참고: Dran and Drop MDN 문서, Drop 오류 수정-스택오버플로우


사용할 이벤트

dragstart & draggable

dragstartdraggable은 내가 드래그하길 원하는 요소에서 사용하게 된다.

원하는 엘리먼트에 draggable 속성을 추가해야 dragstart를 사용할 수 있게 된다.

dataTransfer

나는 드래그 가능한 요소를 다른 컴포넌트에 가져다 놨을 때, 드래그 요소가 가지고 있는 정보를 dispatch 시키기위해 전달하는 과정이 필요했다.
그래서 dataTransfer 기능을 이용했다.

const GoodsBox = ({ order, imgSrc, title, price }: GoodsBoxProps) => {
  // drag했을 때 필요한 정보를 전달하기 위한 dataTransfer.setData 메소드
  const handleDragStart = (e: React.DragEvent) => {
    e.dataTransfer.setData('text/plain', JSON.stringify(문자열로 바꿔놓을 객체값));
  };

  return (
    <GoodsBoxWrapped draggable onDragStart={(e: React.DragEvent) => handleDragStart(e)}>
    	/* 컴포넌트 내용 */
    </GoodsBoxWrapped>
  );
};

export default GoodsBox;

dragover

이 이벤트부터는 드래그한 요소를 놓고 싶은 위치로 생각하면 편하다.
사실은 드래그한 요소를 놓고 원하는 작업을 수행하고자 drop 이벤트만 사용했었는데, 계속 드래그만 인식되고 drop은 인식되질 않았다.

그래서 원인과 해결법을 찾다가 dragover 속성을 내가 사용하지 않은 걸 깨달았다.

  • dragover : 브라우저가 요소를 drop 할 수 있는지 여부를 결정하기 위해 사용하는 이벤트
    dragover 이벤트를 처리하지 않으면 브라우저가 드롭 자체를 허용하지 않아 drop 이벤트가 발생하지 않았던 것이다😅

즉, dragover과 drop은 같이 붙어다녀야하는 필수 요소라고 보면 편할 것 같다.

drop

내가 드래그한 요소를 놓고 싶은 영역에 drop 이벤트를 설정하면 드래그 앤 드롭 기능의 기본은 끝이다!
나는 drop과 관련된 이벤트는 커스텀 핸들러로 다시 만들어, 아까 문자열로 만들어 전달했던 데이터를 다시 객체로 받아와 내가 원하는 액션 함수에 dispatch 시켰다.

const ShoppingList = ({ goodsList }: ShoppingListProps) => {
  const dispatch = useDispatch();

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();

    const data = JSON.parse(e.dataTransfer.getData('text/plain'));
    if (data) {
      dispatch(setRegisterItem(data));
    }
  };

  return (
    <ShoppingListWrapped>
      <ShoppingListTitle>장바구니</ShoppingListTitle>
      <ShoppingListHeader>
        <p>상품정보</p>
        <p>수량</p>
        <p>가격</p>
      </ShoppingListHeader>
      <ListWrapped
        onDragOver={(e: React.DragEvent) => e.preventDefault()}
        onDrop={(e: React.DragEvent) => handleDrop(e)}
      >
		/* 컴포넌트 내용 */
      </ListWrapped>
    </ShoppingListWrapped>
  );
};

export default ShoppingList;

참고로 dragover과 drop에는 e.preventDefault()를 작성해야 한다!
브라우저 자체가 가지고 있는 이벤트가 발생해서 내가 의도한 드래그 앤 드롭 동작에 방해를 하거나, 페이지가 전환되거나 하는 문제를 막고자 작성하는 것이다👀

결과물

profile
💛

0개의 댓글