react์์ drag & drop ๊ธฐ๋ฅ์ ํธํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ๊ตฌํํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋๋ค.
custom hooks๋ก ๊ตฌํํ์์ผ๋ฉฐ drag & drop์ ์ ์ฉํ๊ณ ์ถ์ component์์ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
yarn add react-useful-dnd
npm install react-useful-dnd
component๋ฅผ dragํ ์ ์๋๋ก ํ๊ธฐ ์ํด์๋ useDraggable
์ ์ฌ์ฉํ๊ณ , drag์์๋ฅผ dropํ๊ธฐ ์ํด์๋ useDroppable
์ ์ฌ์ฉํฉ๋๋ค.
drag์์๊ฐ์ state๊ด๋ฆฌ๋ฅผ ์ํด useDnDContext
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
useDnDContext
hooks๋ drag ๊ฐ๋ฅํ ์์๋ค์ ์ํ๊ด๋ฆฌ๋ฅผ ์ ์ดํ๊ธฐ ์ํด ์กด์ฌํ๋ ์์์
๋๋ค. ์ด๊ธฐ ์ํ๊ฐ์ ์ธ์๋ก ๋ฐ์ต๋๋ค.
์ด๊ธฐ ์ํ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ ํ์์ ๊ฐ๋ data์ด์ด์ผ ํฉ๋๋ค.
const initialState = {
first: { data: [...] },
second: { data: [...] }
};
๊ฐ์ฒด์ด๋ฉฐ key๊ฐ์ ํด๋น droppable์ id๊ฐ ๋ ๊ฐ, value๊ฐ์ ์ํ๊ด๋ฆฌ๊ฐ ์ด๋ฃจ์ด์ง ๊ฐ์ด ๋๋ ๊ฐ์ ๋๋ค.
useDnDContext
๋ฅผ ํธ์ถํ๋ฉด DnDStore
, DnDContext
, droppableIds
๋ฅผ ๋ฐํํฉ๋๋ค. ๊ฐ๊ฐ, Store jsx, context, droppable์ ๋ํํ๋ id ๋ฐฐ์ด์ ์๋ฏธํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ํ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
import React from "react";
import DropZone from "DropZone";
import { useDnDContext } from "react-useful-dnd";
const firstItem = [1, 2, 3, 4, 5];
const secondItem = [6, 7, 8, 9, 10];
const initialState = {
first: { data: firstItem },
second: { data: secondItem }
};
function App() {
const [DnDStore, DnDContext, droppableIds] = useDnDContext(initialState);
return (
<DnDStore>
{droppableIds.map(id => (
<DropZone key={id} id={id} context={DnDContext} />
))}
</DnDStore>
);
}
export default App;
DnDStore
๋ด๋ถ์์ ์ฌ์ฉ๋๋ Droppableํ ์์๋ id์ contexts๋ฅผ props๋ก ๋๊ฒจ์ฃผ์ด์ผ ํฉ๋๋ค.
useDraggable
hooks๋ ๋ฐฐ์ด ํํ์ ๊ฐ์ ๋ฐํํ๋ฉฐ, option ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋๊ฒจ์ฃผ์ด์ฌ ํฉ๋๋ค.
option ๊ฐ์ฒด๋ droppableId, groupId๋ฅผ ํ๋กํผํฐ๋ก ๊ฐ์ง๊ณ ์์ต๋๋ค. droppableId๋ ํด๋น dropzone์ id๊ฐ ๋ ๊ฐ์ด๋ฉฐ ๋๊ฒจ์ฃผ์ง ์์ผ๋ฉด ์๋์ผ๋ก ์์ฑ๋ฉ๋๋ค. groupId๋ ํด๋น draggable ์์๊ฐ ์ํ context์ id์ ๋๋ค.
๋ฐฐ์ด์ ์ฒซ๋ฒ์งธ ์์๋ ํด๋น component๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ ref์ด๋ฉฐ, ๋๋ฒ์งธ ์์๋ ํด๋น component์ id ์ ๋๋ค.
ํด๋น component์ ์์ ํ๊ทธ์ ref์ id props๋ฅผ ๋ถ์ฌํด์ค์ผ๋ก์จ ์ฌ์ฉ๊ฐ๋ฅํฉ๋๋ค.
import React from "react";
import { useDraggable } from "react-useful-dnd";
function Draggable({ data, groupId, droppableId }) {
const [draggableRef, id] = useDraggable({ droppableId, groupId });
return (
<div ref={draggableRef} id={id}>
<h3>Draggable #{data}</h3>
</div>
);
}
export default Draggable;
useDroppable
hooks ๋ํ ๋ฐฐ์ด ํํ์ ๊ฐ์ ๋ฐํํ๋ฉฐ option ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋๊ฒจ์ฃผ์ด์ฌ ํฉ๋๋ค.
option ๊ฐ์ฒด๋ id, context๋ฅผ ํ๋กํผํฐ๋ก ๊ฐ์ง๊ณ ์์ต๋๋ค. id๋ ํด๋น dropzone์ id๊ฐ ๋ ๊ฐ์ด๋ฉฐ ๋๊ฒจ์ฃผ์ง ์์ผ๋ฉด ์๋์ผ๋ก ์์ฑ๋ฉ๋๋ค. context๋ ํด๋น droppable ์์๊ฐ ์ํ store์ context์ ๋๋ค.
useDroppable
hooks๋ฅผ ํธ์ถํ์ฌ ๋ฐํ๋๋ ๋ฐฐ์ด์ ์ฒซ๋ฒ์งธ ์์๋ ํด๋น component๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ ref์ด๋ฉฐ, ๋๋ฒ์งธ ์์๋ ํด๋น component์ id ์
๋๋ค.
์ธ๋ฒ์งธ ์์์ธ datas๋ ํด๋น droppable ์์์ state์ด๋ฉฐ drag & drop ์ด๋ฒคํธ์ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ฉ๋๋ค. ๋ค๋ฒ์งธ ์์์ธ groupId๋ ํด๋น droppable ์์๊ฐ ์ํ context์ id์ ๋๋ค.
ํด๋น component์ ์์ ํ๊ทธ์ ref์ id props๋ฅผ ๋ถ์ฌํด์ค์ผ๋ก์จ ์ฌ์ฉ๊ฐ๋ฅํฉ๋๋ค. draggable ์์์ groupId์ droppableId๋ฅผ props๋ก ๋๊ฒจ์ฃผ์ด draggable ์์์์ ์ฌ์ฉํ ์ ์๋๋ก ํด์ฃผ์ด์ผ ํฉ๋๋ค.
import React from "react";
import { useDraggable } from "react-useful-dnd";
import Draggable from "Draggable";
function DropZone({ id, context }) {
const [droppableRef, droppableId, datas, groupId] = useDroppable({
id,
context
});
return (
<div id={droppableId} ref={droppableRef}>
{datas.map(item => (
<Draggable
key={groupId + "-" + droppableId + "-" + item}
data={item}
groupId={groupId}
droppableId={droppableId}
/>
))}
</div>
);
}
export default DropZone;