React Hooks로 드래그 앤 드롭 목록 만들기
25804 단어 reactdraganddropreacthooks
결과:
기본 사항
전체 API 설명서를 읽는 것이 좋지만 가장 중요한 사항은 다음과 같습니다.
드래그할 항목
draggable
속성을 true
로 설정하고 onDragStart
이벤트 핸들러를 첨부하여 끌 수 있는 DOM 요소를 정의합니다.
<div draggable="true" onDragStart={startDragging}>
Drag Me 🍰
</div>
드롭 장소
드롭 영역을 정의하려면 onDrop
및 onDragOver
이벤트 핸들러가 연결되어 있어야 합니다.
<section onDrop={updateDragAndDropState} onDragOver={receiveDraggedElements}>
Drop here 🤲🏻
</section>
이 예에서 각 목록 항목은 드래그하여 동일한 목록을 재정렬하고 드래그되는 항목의 위치와 드롭하려는 위치에 대해 알아야 하기 때문에 드래그 가능한 요소이자 드롭 영역이 됩니다. 거기에서 렌더링되는 목록 항목의 배열을 다시 계산하고 업데이트합니다.
DataTransfer 개체 정보
API는 끌어온 데이터와 상호 작용하기 위한 this object 및 setData()
및 getData()
와 같은 몇 가지 편리한 메서드를 제공합니다. 많은 DnD 구현에서 볼 수 있기 때문에 언급하고 싶었지만 React 상태가 있고 Hooks를 가지고 놀고 싶기 때문에 사용하지 않을 것입니다!
Click here 다양한 드래그 가능 요소와 드롭 영역이 있는 드래그 앤 드롭과 DataTransfer 개체 사용의 예를 참조하십시오.
다이빙하자
참고: 스타일 지정에 중점을 두지 않을 것입니다. 이 예제를 복제하는 경우 CodePen에서 SCSS를 자유롭게 복사하십시오.
베어본 구성 요소:
const items = [
{ number: "1", title: "🇦🇷 Argentina"},
{ number: "2", title: "🤩 YASS"},
{ number: "3", title: "👩🏼💻 Tech Girl"},
{ number: "4", title: "💋 Lipstick & Code"},
{ number: "5", title: "💃🏼 Latina"},
]
// The only component we'll have:
// It will loop through the items
// and display them.
// For now, this is a static array.
const DragToReorderList = () => {
return(
<section>
<ul>
{items.map( (item, index) => {
return(
<li key={index} >
<span>{item.number}</span>
<p>{item.title}</p>
<i class="fas fa-arrows-alt-v"></i>
</li>
)
})}
</ul>
</section>
)
}
ReactDOM.render(
<DragToReorderList />,
document.getElementById("root")
);
항목을 드래그할 수 있도록 설정
2가지가 필요합니다.
<div draggable="true" onDragStart={startDragging}>
Drag Me 🍰
</div>
<section onDrop={updateDragAndDropState} onDragOver={receiveDraggedElements}>
Drop here 🤲🏻
</section>
참고: 스타일 지정에 중점을 두지 않을 것입니다. 이 예제를 복제하는 경우 CodePen에서 SCSS를 자유롭게 복사하십시오.
베어본 구성 요소:
const items = [
{ number: "1", title: "🇦🇷 Argentina"},
{ number: "2", title: "🤩 YASS"},
{ number: "3", title: "👩🏼💻 Tech Girl"},
{ number: "4", title: "💋 Lipstick & Code"},
{ number: "5", title: "💃🏼 Latina"},
]
// The only component we'll have:
// It will loop through the items
// and display them.
// For now, this is a static array.
const DragToReorderList = () => {
return(
<section>
<ul>
{items.map( (item, index) => {
return(
<li key={index} >
<span>{item.number}</span>
<p>{item.title}</p>
<i class="fas fa-arrows-alt-v"></i>
</li>
)
})}
</ul>
</section>
)
}
ReactDOM.render(
<DragToReorderList />,
document.getElementById("root")
);
항목을 드래그할 수 있도록 설정
2가지가 필요합니다.
draggable
속성onDragStart
이벤트 핸들러const onDragStart = (event) => {
// It receives a DragEvent
// which inherits properties from
// MouseEvent and Event
// so we can access the element
// through event.currentTarget
// Later, we'll save
// in a hook variable
// the item being dragged
}
<li key={index} draggable="true" onDragStart={onDragStart}>
<span>{item.number}</span>
<p>{item.title}</p>
<i class="fas fa-arrows-alt-v"></i>
</li>
멋진! 이제 드래그할 수 있습니다.
드롭 영역으로 변환
2개의 이벤트 핸들러가 필요합니다.
onDrop
onDragOver
const onDragOver = (event) => {
// It also receives a DragEvent.
// Later, we'll read the position
// of the item from event.currentTarget
// and store the updated list state
// We need to prevent the default behavior
// of this event, in order for the onDrop
// event to fire.
// It may sound weird, but the default is
// to cancel out the drop.
event.preventDefault();
}
const onDrop = () => {
// Here, we will:
// - update the rendered list
// - and reset the DnD state
}
<li
key={index}
draggable="true"
onDragStart={onDragStart}
onDragOver={onDragOver}
onDrop={onDrop}
>
<span>{item.number}</span>
<p>{item.title}</p>
<i class="fas fa-arrows-alt-v"></i>
</li>
기본 동작here에 대해 자세히 읽어보십시오. 문서의 해당 부분을 읽을 때까지 몇 시간의 작업 시간을 잃었습니다. 🤷🏼♀️
또한
onDragEnter
를 사용하여 현재 호버링된 드롭 영역에 일부 스타일을 설정할 수 있습니다.
onDragEnter
fires once, whereasonDragOver
fires every few hundred milliseconds, so it's ideal to add a css class for instance.
즉, 나는
onDragEnter
가 신뢰할 수 없는 것으로 나타났기 때문에 onDragOver
에서 일부 상태/플래그를 확인하고 onDragEnter
대신 이를 기반으로 스타일 업데이트를 수행하기로 했습니다.또한 스타일을 제거하기 위해 드롭 영역을 가리키면 실행되는
onDragLeave
를 사용할 수 있습니다.역동적으로 만들기
기능적 구성 요소에서 React 상태를 사용할 수 있으려면 변수와 업데이트 기능을 제공하는
useState
후크를 사용합니다. 💯우리는 그것들 중 2개를 가질 것입니다:
const initialDnDState = {
draggedFrom: null,
draggedTo: null,
isDragging: false,
originalOrder: [],
updatedOrder: []
}
const items = [
{ number: "1", title: "🇦🇷 Argentina"},
{ number: "2", title: "🤩 YASS"},
{ number: "3", title: "👩🏼💻 Tech Girl"},
{ number: "4", title: "💋 Lipstick & Code"},
{ number: "5", title: "💃🏼 Latina"},
]
const DragToReorderList = () => {
// We'll use the initialDndState created above
const [dragAndDrop, setDragAndDrop] = React.useState( initialDnDState );
// The initial state of "list"
// is going to be the static "items" array
const [list, setList] = React.useState( items );
//...
// So let's update our .map() to loop through
// the "list" hook instead of the static "items"
return(
//...
{list.map( (item, index) => {
return(
// ...
)
})}
//...
)
}
onDragStart 연결
이 함수는 드래그 시작을 처리합니다.
먼저
data-position
속성을 추가하고 각 항목의 index
를 저장합니다.<li
data-position={index}
//...
>
그 다음에:
const onDragStart = (event) => {
// We'll access the "data-position" attribute
// of the current element dragged
const initialPosition = Number(event.currentTarget.dataset.position);
setDragAndDrop({
// we spread the previous content
// of the hook variable
// so we don't override the properties
// not being updated
...dragAndDrop,
draggedFrom: initialPosition, // set the draggedFrom position
isDragging: true,
originalOrder: list // store the current state of "list"
});
// Note: this is only for Firefox.
// Without it, the DnD won't work.
// But we are not using it.
event.dataTransfer.setData("text/html", '');
}
onDragOver 연결
const onDragOver = (event) => {
event.preventDefault();
// Store the content of the original list
// in this variable that we'll update
let newList = dragAndDrop.originalOrder;
// index of the item being dragged
const draggedFrom = dragAndDrop.draggedFrom;
// index of the drop area being hovered
const draggedTo = Number(event.currentTarget.dataset.position);
// get the element that's at the position of "draggedFrom"
const itemDragged = newList[draggedFrom];
// filter out the item being dragged
const remainingItems = newList.filter((item, index) => index !== draggedFrom);
// update the list
newList = [
...remainingItems.slice(0, draggedTo),
itemDragged,
...remainingItems.slice(draggedTo)
];
// since this event fires many times
// we check if the targets are actually
// different:
if (draggedTo !== dragAndDrop.draggedTo){
setDragAndDrop({
...dragAndDrop,
// save the updated list state
// we will render this onDrop
updatedOrder: newList,
draggedTo: draggedTo
})
}
}
마지막으로, 버려! 🌟
const onDrop = () => {
// we use the updater function
// for the "list" hook
setList(dragAndDrop.updatedOrder);
// and reset the state of
// the DnD
setDragAndDrop({
...dragAndDrop,
draggedFrom: null,
draggedTo: null,
isDragging: false
});
}
엄청난!
이 펜에 대한 전체 코드 예제를 가져옵니다.
https://codepen.io/florantara/pen/jjyJrZ
이 API에 대한 단점
마음에 드셨다면 자유롭게 공유해주세요 💓
Reference
이 문제에 관하여(React Hooks로 드래그 앤 드롭 목록 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/florantara/creating-a-drag-and-drop-list-with-react-hooks-4c0i텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)