react-draggable로 drag 동작 구현

kyoung·2025년 3월 14일

react-draggable 라이브러리를 선택한 이유

구현 사진
위와 같은 윈도우 화면을 구현하는 과정에서, 각 창과 아이콘을 드래그로 이동시킬 수 있는 동작이 필요했다.
drag&drop 기능을 구현해주는 라이브러리로는

을 많이 사용하는데, 나는 단순히 컴포넌트를 이동시키는 동작만 필요했기 때문에 react-draggable을 사용하기로 했다.

구현

1. 설치

npm i react-draggable

기본적으로 typeScript를 지원하기 때문에, 따로 설정할 필요는 없다.

2. 적용

     <Draggable
        axis="x"
        handle=".handle"
        defaultPosition={{x: 0, y: 0}}
        bounds={left ?: number ,  top ?: number ,  
                right ?: number ,  bottom ?: number}
        position={null}
        grid={[25, 25]}
        scale={1}
        onStart={this.handleStart}
        onDrag={this.handleDrag}
        onStop={this.handleStop}>

많은 커스텀 요소들이 있지만, 프로젝트에서 사용한 요소는 다음과 같다.

  • handel
    컴포넌트 내의 특정 요소를 클릭하고 있을 때에만 드래그 할 수 있도록 제한하고 싶을 때 사용한다.
    "%" 나 "vh"는 사용할 수 없고, "px" 단위만 사용 가능하다.

  • bounds
    컴포넌트의 이동 경계를 지정할 때 사용한다.

  • onDrag : DraggableEventHandler

  • onStop : DraggableEventHandler

import Draggable from "react-draggable";
import { useRef, useState } from "react";


const MainPage = () => {
  const [isDragging, setIsDragging] = useState(false);
  const nodeRef = useRef(null);

  const handleOnDrag = () => {
    setIsDragging(true);
  };

  const handleStopDrag = () => {
    setTimeout(() => {
      setIsDragging(false);
    }, 100);
  };

  return (
       <IconList>
          {data.map((icon) => {
            return (
              <Draggable
                nodeRef={nodeRef}
                onDrag={() => handleOnDrag()}
                onStop={handleStopDrag}
                key={icon.name}
              >
                <Icon
                  key={icon.id}
                  onClick={() => {
                    if (isDragging) return;
                    icon.isModal ? onNothingClick() : navigate(icon.path);
                  }}
                  ref={nodeRef}
                >
                  <Img src={icon.img} />
                  <Name>{icon.name}</Name>
                </Icon>
              </Draggable>
            );
          })}
       </IconList>
)

각 아이콘을 드래그 할 때, 드래그 뿐만 아니라 클릭 이벤트도 같이 동작하는 것을 막기 위하여 드래그 하는 도중에는 isDragging을 true로 전환하고, isDragging을 true일 때엔 if (isDragging) return;을 통해 클릭을 막도록 했다.

그리고 ReactDOM.findDOMNode()가 더이상 사용되지 않기 때문에 <Draggable>을 제대로 동작 시키기 위해서 nodeRef={nodeRef}ref={nodeRef}를 사용한다.

 <Draggable
      nodeRef={nodeRef}
      handle=".top-container"
    >
      <Container ref={nodeRef}>
        <TopContainer className="top-container">
          
          ...
        
        </TopContainer>

          ...
          
      <Container>
  </Draggable>

핸들로 사용하고 싶은 요소에 className을 주고, handle="클래스 네임" 을 전달해 해당 부분을 클릭했을 때에만 드래그가 가능하도록 설정했다.

참고 자료
react-draggable 공식예제
react-draggable Drag&Drop 구현

0개의 댓글