커스텀 훅 분리 및 react query 최적화
This commit is contained in:
92
frontend/hooks/useDragAndDrop.ts
Normal file
92
frontend/hooks/useDragAndDrop.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
type DragStartEvent,
|
||||
type DragEndEvent,
|
||||
} from "@dnd-kit/core";
|
||||
import { arrayMove, sortableKeyboardCoordinates } from "@dnd-kit/sortable";
|
||||
|
||||
export interface DragAndDropItem {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface UseDragAndDropProps<T extends DragAndDropItem> {
|
||||
items: T[];
|
||||
onReorder: (reorderedItems: Array<{ id: string; sortOrder: number }>) => Promise<void>;
|
||||
getItemId: (item: T) => string;
|
||||
}
|
||||
|
||||
export function useDragAndDrop<T extends DragAndDropItem>({ items, onReorder, getItemId }: UseDragAndDropProps<T>) {
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
|
||||
// 드래그 센서 설정
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, {
|
||||
activationConstraint: {
|
||||
distance: 8, // 8px 이동 후 드래그 시작
|
||||
},
|
||||
}),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
|
||||
// 드래그 시작 핸들러
|
||||
const handleDragStart = (event: DragStartEvent) => {
|
||||
setActiveId(event.active.id as string);
|
||||
};
|
||||
|
||||
// 드래그 종료 핸들러
|
||||
const handleDragEnd = async (event: DragEndEvent) => {
|
||||
setActiveId(null);
|
||||
const { active, over } = event;
|
||||
|
||||
if (over && active.id !== over.id) {
|
||||
const oldIndex = items.findIndex((item) => getItemId(item) === active.id);
|
||||
const newIndex = items.findIndex((item) => getItemId(item) === over.id);
|
||||
|
||||
if (oldIndex !== -1 && newIndex !== -1) {
|
||||
const newOrder = arrayMove(items, oldIndex, newIndex);
|
||||
|
||||
// 순서 업데이트를 위한 데이터 준비
|
||||
const reorderedItems = newOrder.map((item, index) => ({
|
||||
id: getItemId(item),
|
||||
sortOrder: index + 1,
|
||||
}));
|
||||
|
||||
try {
|
||||
await onReorder(reorderedItems);
|
||||
} catch (error) {
|
||||
console.error("순서 변경 실패:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 현재 드래그 중인 아이템 찾기
|
||||
const activeItem = activeId ? items.find((item) => getItemId(item) === activeId) : null;
|
||||
|
||||
return {
|
||||
// 상태
|
||||
activeId,
|
||||
activeItem,
|
||||
|
||||
// 센서 및 핸들러
|
||||
sensors,
|
||||
handleDragStart,
|
||||
handleDragEnd,
|
||||
|
||||
// DndContext props
|
||||
dndContextProps: {
|
||||
sensors,
|
||||
collisionDetection: closestCenter,
|
||||
onDragStart: handleDragStart,
|
||||
onDragEnd: handleDragEnd,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user