📱테스트 환경
"react": "18.3.0",
"react-dom": "18.3.0"
드래그 앤 드랍 기능을 만들기 위해서
여러 라이브러리를 살펴봤지만 폴더구조까지 가진 라이브러리가
딱히 보이지도않았고 맘에 드는게 없었다.
그러다가 react-complex-tree 를 딱 봤는데
react-complex-tree
Unopinionated Accessible Tree Component with Multi-Select and Drag-And-Drop. Latest version: 2.4.6, last published: a month ago. Start using react-complex-tree in your project by running `npm i react-complex-tree`. There are 21 other projects in the npm re
www.npmjs.com
내가 원하던 그것 .. 그 자체 ..
사용량도 많고 유지보수도 잘되는 것 같아 이걸로 사용하기로 맘먹었는데
사용방법이 조금 까다로워서 좀 오래걸렸지만 방법은 다음과같다.
npm i react-complex-tree
모듈 받아주고
import React, {useState} from "react";
import {
ControlledTreeEnvironment,
Tree,
TreeItem,
TreeItemIndex,
DraggingPosition,
} from "react-complex-tree";
import "react-complex-tree/lib/style-modern.css";
interface TreeItemData extends TreeItem {
index: TreeItemIndex;
isFolder?: boolean;
children: TreeItemIndex[];
data: string;
}
interface TreeData {
[key: string]: TreeItemData;
}
interface ItemsProps {
items: TreeData;
setItems: any;
}
const CategoryEditor: React.FC<ItemsProps> = ({items, setItems}) => {
const [viewState, setViewState] = useState({
expandedItems: Object.keys(items).filter(
(key) => items[key].isFolder
) as TreeItemIndex[],
});
const handleDrop = (
draggedItems: TreeItem<TreeItemIndex>[],
target: DraggingPosition
) => {
const updatedItems = {...items};
console.log(target)
draggedItems.forEach((draggedItem) => {
// Remove the dragged item from its current parent
const currentParent = Object.values(updatedItems).find((item) =>
item.children.includes(draggedItem.index)
);
if (currentParent) {
currentParent.children = currentParent.children.filter(
(childId) => childId !== draggedItem.index
);
}
if (target.targetType === "item") {
// Drop on an item (add to its children if it's a folder)
const targetItem = updatedItems[target.targetItem as string];
if (targetItem.isFolder) {
targetItem.children.push(draggedItem.index);
} else {
// If the target is not a folder, add the item as its sibling
const parentItem = Object.values(updatedItems).find((item) =>
item.children.includes(target.targetItem as TreeItemIndex)
);
if (parentItem) {
const index = parentItem.children.indexOf(target.targetItem as TreeItemIndex);
parentItem.children.splice(index + 1, 0, draggedItem.index);
}
}
} else if (target.targetType === "between-items" && target.parentItem) {
// 두 아이템 사이에 추가
const parentItem = updatedItems[target.parentItem];
if (parentItem) {
const index = target.childIndex || 0;
parentItem.children.splice(index, 0, draggedItem.index);
}
} else if (target.targetType === "root") {
// 루트 레벨에 추가
updatedItems["root"].children.push(draggedItem.index);
}
});
setItems(updatedItems);
};
return (
<ControlledTreeEnvironment
items={items}
getItemTitle={(item) => item.data}
viewState={{
"tree-2": {
expandedItems: viewState.expandedItems,
},
}}
onExpandItem={(item, treeId) => {
setViewState((prev) => ({
...prev,
expandedItems: [...prev.expandedItems, item.index],
}));
}}
onCollapseItem={(item, treeId) => {
setViewState((prev) => ({
...prev,
expandedItems: prev.expandedItems.filter((id) => id !== item.index),
}));
}}
onDrop={handleDrop} // 드래그 앤 드롭 이벤트 핸들러
canDragAndDrop={true}
canDropOnFolder={true}
canReorderItems={true}
>
<Tree treeId="tree-2" rootItem="root" treeLabel="Tree Example"/>
</ControlledTreeEnvironment>
);
};
export default CategoryEditor;
이렇게 만들어주고 나면 어느 페이지에서건
데이터만 넣어주면 끝!
const Category = () => {
const [categories, setCategories] = useState({});
return (
<CateListBox>
<CategoryEditor items={categories} setItems={setCategories}/>
</CateListBox>
)
}
이런식으로 작성해주면 완성된다~
해당 라이브러리를 사용하는거기 때문에 데이터 구조는 반드시 지켜서 사용해줘야한다.
'Javascript > React' 카테고리의 다른 글
[React] Antd DatePicker 한글 패치 하는 방법 (0) | 2024.12.20 |
---|---|
[React] JSX.Element 곧 사용할 수 없게 될 심볼이 사용되었습니다 (0) | 2024.11.28 |
[React] xlsx-js-style (1) | 2024.11.26 |
[React] Styled-Compoent (1) | 2024.11.15 |
[React] Moment 대신 Day.js (0) | 2024.11.14 |