drag and drop의 기능이 필요해 라이브러리를 찾던 중 react-beautiful-dnd 라이브러리를 찾았는데 클래스형으로는 예제가 있지만 함수형은 없는 것같아 검색했습니다.
코드샌드박스에 누군가 잘 올려준 게시물 덕분에 해결
https://codesandbox.io/s/9z5tn?file=/src/index.js
vertical-list - CodeSandbox
vertical-list using react, react-beautiful-dnd, react-dom
codesandbox.io
저같은 경우 App.js에서 <PageList /> 에게 props로 [pageList, setPageList]를 넘겨주고 이를 pageList 컴포넌트에서 받아 react-beautiful-dnd로 렌더하는 식입니다.
import React, { useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
// a little function to help us with reordering the result
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
const grid = 8;
const getItemStyle = (isDragging, draggableStyle) => ({
// some basic styles to make the items look a bit nicer
userSelect: "none",
padding: grid * 2,
margin: `0 0 ${grid}px 0`,
// change background colour if dragging
background: isDragging ? "lightgreen" : "grey",
// styles we need to apply on draggables
...draggableStyle,
});
const getListStyle = (isDraggingOver) => ({
background: isDraggingOver ? "lightblue" : "lightgrey",
padding: grid,
width: 500,
position: "relative",
});
const queryAttr = "data-rbd-drag-handle-draggable-id";
const InputList = (props) => {
const [placeholderProps, setPlaceholderProps] = useState({});
const { pageList, setPageList } = props;
// const [items, setItems] = useState(getItems(10));
const onDragEnd = (result) => {
// dropped outside the list
if (!result.destination) {
return;
}
setPlaceholderProps({});
setPageList((items) =>
reorder(items, result.source.index, result.destination.index)
);
};
const onDragUpdate = (update) => {
if (!update.destination) {
return;
}
const draggableId = update.draggableId;
const destinationIndex = update.destination.index;
const domQuery = `[${queryAttr}='${draggableId}']`;
const draggedDOM = document.querySelector(domQuery);
if (!draggedDOM) {
return;
}
const { clientHeight, clientWidth } = draggedDOM;
const clientY =
parseFloat(window.getComputedStyle(draggedDOM.parentNode).paddingTop) +
[...draggedDOM.parentNode.children]
.slice(0, destinationIndex)
.reduce((total, curr) => {
const style = curr.currentStyle || window.getComputedStyle(curr);
const marginBottom = parseFloat(style.marginBottom);
return total + curr.clientHeight + marginBottom;
}, 0);
setPlaceholderProps({
clientHeight,
clientWidth,
clientY,
clientX: parseFloat(
window.getComputedStyle(draggedDOM.parentNode).paddingLeft
),
});
};
// Normally you would want to split things out into separate components.
// But in this example everything is just done in one place for simplicity
return (
<DragDropContext onDragEnd={onDragEnd} onDragUpdate={onDragUpdate}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={getListStyle(snapshot.isDraggingOver)}
>
{pageList.map((item, index) => (
<Draggable
key={`item${item.index}`}
draggableId={`item-${item.index}`}
index={index}
>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getItemStyle(
snapshot.isDragging,
provided.draggableProps.style
)}
>
<label>index: {index}</label>
<br />
<label>item.index: {item.index}</label>
<br />
<label>component: {item.component}</label>
<div>
<img src={item.url} alt="" height="200" />
<br />
<label>url: {item.url}</label>
</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
{/* <CustomPlaceholder snapshot={snapshot} /> */}
<div
style={{
position: "absolute",
top: placeholderProps.clientY,
left: placeholderProps.clientX,
height: placeholderProps.clientHeight,
background: "tomato",
width: placeholderProps.clientWidth,
}}
/>
</div>
)}
</Droppable>
</DragDropContext>
);
};
export default InputList;
바꾼건 <Droppable /> 안에 items.map() -> pageList.map() 이랑 <Draggable />안에 key, draggableId, 내용물 정도입니다.
draggableId에다가 숫자만 넣으면 requires string~~~ 이라는 경고문이 나오는데 이는 앞에 문자열을 붙여주면 해결.
사진이 제대로 변함!!!!
'프론트엔드 > React' 카테고리의 다른 글
react_dom__WEBPACK_IMPORTED_MODULE_1__.createRoot is not a function (0) | 2022.05.05 |
---|---|
어떻게 된거냐면요 (0) | 2021.07.19 |
axios 사용한 리액트 컴포넌트 (0) | 2021.07.12 |
현재 진행중인 React 프로젝트 엿보기 (0) | 2021.07.06 |
mac, gradle, react-bootstrap 연동 (0) | 2021.06.30 |