dnd-kit 적용기..

Jinmin Kim·2025년 5월 7일

1️⃣ dnd-kit Sortable 기본 사용법

📌 설치 및 임포트

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
import {
  DndContext, useSensor, useSensors,
  MouseSensor, TouchSensor, closestCenter
} from "@dnd-kit/core";
import {
  SortableContext, useSortable,
  arrayMove, verticalListSortingStrategy
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";

📌 컨텍스트 감싸기

const sensors = useSensors(
  useSensor(MouseSensor, { activationConstraint: { distance: 5 } }),
  useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 5 } })
);

<DndContextsensors={sensors}
  collisionDetection={closestCenter}
  onDragEnd={handleDragEnd}
>
  <SortableContextitems={data.map(i => i.나의Id값으로지정할값 )}
    strategy={verticalListSortingStrategy}
  >
    {data.map(item => (
      <SortableItem key={item.나의Id값으로지정할값} id={item.나의Id값으로지정할값}>
        {/* 내용 */}
      </SortableItem>
    ))}
  </SortableContext>
</DndContext>

📌 SortableItem 구현

function SortableItem({ id, children }) {
  const {
    attributes, listeners,
    setNodeRef, transform,
    transition, isDragging
  } = useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    cursor: isDragging ? "grabbing" : undefined
  };

  return (
    <li ref={setNodeRef} style={style} {...attributes} {...listeners}>
      {children}
    </li>
  );
}

2️⃣ onDragEnd 핸들링

function handleDragEnd({ active, over }) {
  if (!over) return;
  const oldIndex = userGroupChildren.findIndex(
    item => item.나의Id값으로지정할값 === active.id
  );
  const newIndex = userGroupChildren.findIndex(
    item => item.나의Id값으로지정할값 === over.id
  );
  setUserGroupChildren(
    arrayMove(userGroupChildren, oldIndex, newIndex)
  );
}

3️⃣ 내가 겪은 실수 & 해결법

🌟 실수 1: items prop 불일치

  • 문제: SortableContextitems에 실제 id 배열을 넘기지 않아 transform이 계속 undefined 발생
  • 해결:
items={data.map(i => i.나의Id값으로지정할값)}

로 명확히 id 값만 공유

🌟 실수 2: handleDragEnd에서 id 미공유

  • 문제: active.id, over.id나의Id값으로지정할값과 매칭되지 않음 → findIndex 실패
  • 해결:
    - useSortable({ id: item.나의Id값으로지정할값 })
    - findIndex(item => item.나의Id값으로지정할값 === active.id)
    를 정확히 동일한 타입·값으로 유지

4️⃣ 다음에도 실수하지 않으려면

  1. 항상 items 배열 확인하기
    • SortableContext에 넘기는 itemsuseSortable({ id }) id 값이 100% 일치하는지
  2. id 타입 동기화하기
    • 숫자 vs 문자열 혼용 금지! 둘 중 하나로 통일
  3. transform 값 디버깅
    • console.log(transform) 이전에 Context와 id 배열이 제대로 세팅됐는지 체크
  4. styled-components 사용 시 ref·style 전달 확인
    • 커스텀 컴포넌트면 forwardRef 적용하기
profile
Let's do it developer

0개의 댓글