Skip to content

useMountDragEvent

lybell edited this page Aug 11, 2024 · 1 revision
const { onPointerDown, dragState } = useMountDragEvent({onDragStart, onDrag, onDragEnd});

✨ 어떤 기능을 하나요?

useMountDragEvent는 드래그 이벤트를 선언하는 리액트 훅입니다.

useMountDragEvent는 특정 요소에 드래그 이벤트를 부착하기 위해 사용됩니다. 네이티브 drag & drop api의 제한을 해제하기 위해, window에 포인터 이벤트를 마운트하는 형태로 동작합니다. 드래그 시작, 드래그 도중, 드래그 종료 이벤트를 선언해서 useMountDragEvent 훅에 부착시키면, 드래그 이벤트를 등록시키고, 드래그 시작에 사용되는 onPointerDown 함수와 현재 드래그 상태를 받아오는 dragState를 인자로 반환합니다.

💡 사용 예제

import { useState, useRef, useCallback } from "react";
import useMountDragEvent from "@/common/useMountDragEvent.js";

function App() {
  // 드래그하면 변경될 상태를 정의합니다.
  const prevState = useRef({ x: 0, y: 0, mouseX: 0, mouseY: 0 });
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);

  // 드래그 시작, 드래그 중, 드래그 종료 시 발생할 이벤트를 정의합니다.
  const onDragStart = useCallback(
    function ({ x: mouseX, y: mouseY }) {
      Object.assign(prevState.current, { mouseX, mouseY, x, y });
    },
    [x, y],
  );
  const onDrag = useCallback(function (mouse) {
    setX(prevState.current.x + mouse.x - prevState.current.mouseX);
    setY(prevState.current.y + mouse.y - prevState.current.mouseY);
  }, []);

  const { onPointerDown, dragState } = useMountDragEvent({
    onDragStart,
    onDrag,
  });

  const style = { transform: `translate(${x}px, ${y}px)` };

  // 훅에서 반환한 onPointerDown 함수를 드래그의 대상이 되는 엘리먼트에 부착시키세요.
  return (
    <div className="w-full h-screen flex justify-center items-center">
      <div style={style} className={`size-12 ${dragState ? "bg-blue-400" : "bg-neutral-500"}`} onPointerDown={onPointerDown}>
        {dragState ? "드래그중..." : "드래그하세요!"}
      </div>
    </div>
  );
}

위의 예제를 실제로 돌려보시면, 드래그하세요라는 텍스트가 적힌 사각형을 드래그해서 원하는 곳에 놓을 수 있습니다.

  • 드래그하면 바뀔 상태(보통은 위치 정보)를 정의합니다.
  • 드래그 시작, 드래그 중, 드래그 종료 이벤트를 정의합니다.
  • useMountDragEvent 훅에 드래그 시작, 드래그 중, 드래그 종료 이벤트를 묶은 객체를 인자로 전달합니다. 반환값으로 onPointerDown, dragState이 반환됩니다.
  • onPointerDown 함수를 드래그를 시작하고 싶은 엘리먼트에 onPointerDown 이벤트로 부착하세요.
  • 요소가 드래그 중인지에 따라 다르게 렌더링하고 싶다면, dragState 상태를 이용하면 됩니다. 위의 예제에서는 dragState에 따라 배경을 변경시키고, 요소의 텍스트를 변경했습니다.

🔌 인터페이스

const { onPointerDown, dragState } = useMountDragEvent({onDragStart, onDrag, onDragEnd});

매개변수

  • onDragStart : 드래그 시작 시 호출할 이벤트입니다. 생략 가능합니다.
  • onDrag : 드래그 도중 호출할 이벤트입니다.
  • onDragEnd : 드래그 완료 시 호출할 이벤트입니다. 생략 가능합니다.

반환값

  • onPointerDown : 드래그 시작을 실제로 유발하는 함수입니다. 해당 함수를 호출하면 드래그 시작 상태가 됩니다. 이 함수를 onPointerDown 이벤트에 부착하세요.
  • dragState : 현재 드래그 중이라면 true를, 드래그되고 있지 않다면 false를 반환합니다.

❗ 주의사항

드래그 이벤트에서는 상태가 드래그할 때마다 1초에 60번까지도 변경됩니다. 이에 따라, 드래그 함수를 useCallback으로 감싸주지 않는다면 함수가 계속 생성되어서, 이벤트를 계속 마운트하고 언마운트하는 부작용이 일어나게 됩니다.

반드시 드래그 이벤트 함수는 useCallback으로 감싸주시기 바랍니다.

Clone this wiki locally