React에서 드래그 앤 드랍 직접 구현하기

2023. 1. 4.·🎨 프론트엔드 공부/React & Next

📍참고

https://www.aurigait.com/blog/drag-and-drop-in-react-without-using-any-external-library/

 

Drag and Drop in React without using any External Library - Auriga IT

Drag and Drop feature in React with little effort using useRef hook. Here we'll see it in action by implementing an easy drag and drop list.

www.aurigait.com

 

https://developer.mozilla.org/ko/docs/Web/API/HTML_Drag_and_Drop_API

 

HTML 드래그 앤 드롭 API - Web API | MDN

HTML 드래그 앤 드롭 인터페이스는 파이어폭스와 다른 브라우저에서 어플리케이션이 드래그 앤 드롭 기능을 사용하게 해줍니다. 이 기능을 이용해 사용자는 draggable 요소를 마우스로 선택해 droppa

developer.mozilla.org

 

- HTML Drag and Drop API

 

📍1. 리스트 생성 및 원소들에 draggable 어트리뷰트 부여

- element에 draggable을 부여하기만 해도 드래그 효과가 가능

 

📍2. useRef 훅으로 드래그되는 아이템 추적하기

- useRef 훅으로 드래그될 아이템의 리스트 내 인덱스를 기억

- 드래그 시작 이벤트에 반응하는 onDragStart 이벤트 리스너를 draggable 요소에 부착

 

📍3. 드랍될 위치의 아이템추적하기

- useRef 훅으로 드랍될 위치(드래그중인 요소가 침범한 기존 위치)의 인덱스를 기억

- onDragEnter 이벤트 리스너를 draggable 요소에 부착

- onDragEnter 이벤트 리스너 : 드래그중인 커서가 들어올 때 (이벤트 리스너가 부착된 요소 안으로) 발동

- 현재 드래그중인 요소에도 onDragEnter 이벤트 리스너가 부착되어 있음

 

📍4. draggable element들의 리스트 순서 재배열

- onDragEnd 이벤트리스너는 드래그 이벤트가 끝나면 발동

- splice() 함수를 이용해 드래그 시작 인덱스의 원소를 제거 (deleteCount = 1)

- 그리고 splice 함수로 dragEnter된 인덱스에 useRef로 저장한 드래그 시작 인덱스를 추가 (deleteCount = 0)

이 때, deleteCount가 0이므로, 기존 요소가 제거되지 않고 새로운 원소에 의해 한 칸 밀림

 

📍5. drag over 애니메이션 효과 제거

- 커서의 금지 효과를 제거하기 위해 onDragOver 이벤트 리스너에 event.preventDefault() 를 추가해 준다

 

📍완성된 코드

https://codesandbox.io/s/dnd-k9wvtw?file=/src/App.js 

 

dnd - CodeSandbox

dnd by jong-k using react, react-dom, react-scripts

codesandbox.io

 

import React, { useState, useRef } from "react";
import "./styles.css";

const App = () => {
  const dragItem = useRef(); // 드래그할 아이템의 인덱스
  const dragOverItem = useRef(); // 드랍할 위치의 아이템의 인덱스
  const [list, setList] = useState([
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6"
  ]);

  // 드래그 시작될 때 실행
  const dragStart = (e, position) => {
    dragItem.current = position;
    console.log(e.target.innerHTML);
  };

  // 드래그중인 대상이 위로 포개졌을 때
  const dragEnter = (e, position) => {
    dragOverItem.current = position;
    console.log(e.target.innerHTML);
  };

  // 드랍 (커서 뗐을 때)
  const drop = (e) => {
    const newList = [...list];
    const dragItemValue = newList[dragItem.current];
    newList.splice(dragItem.current, 1);
    newList.splice(dragOverItem.current, 0, dragItemValue);
    dragItem.current = null;
    dragOverItem.current = null;
    setList(newList);
  };

  return (
    <>
      {list &&
        list.map((item, idx) => (
          <div
            key={idx}
            style={{
              backgroundColor: "lightblue",
              margin: "20px 25%",
              textAlign: "center",
              fontSize: "40px"
            }}
            draggable
            onDragStart={(e) => dragStart(e, idx)}
            onDragEnter={(e) => dragEnter(e, idx)}
            onDragEnd={drop}
            onDragOver={(e) => e.preventDefault()}
          >
            {item}
          </div>
        ))}
    </>
  );
};

export default App;
'🎨 프론트엔드 공부/React & Next' 카테고리의 다른 글
  • Next.js 을 사용하는 이유
  • React에서 로컬 캐싱 직접 구현하기
  • React를 사용하는 이유 3가지
  • useReducer Hook
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (516) N
      • 🎨 프론트엔드 공부 (253) N
        • JS & TS (92) N
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
React에서 드래그 앤 드랍 직접 구현하기
상단으로

티스토리툴바