react-beautiful-dnd 을 사용하여 React에서 깔끔하고 사용하기 쉬운 드래그, 드롭, 애니메이션을 적용하는 방법에 대해 알아보겠습니다.
설치
1 $ npm i react-beautiful-dnd
TypeScript 사용 시 추가로 설치합니다.
1 $ npm i --save-dev @types/react-beautiful-dnd
사용
임시 데이터 **[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]**를 사용하여 카드 형태의 드래그, 드롭을 구현해 봤습니다.
1 2 3 4 5 6 7 import { atom } from 'recoil' ;export const toDoState = atom({ key: 'toDo' , default : ['a' , 'b' , 'c' , 'd' , 'e' , 'f' ], });
DragDropContext
, Draggable
, Droppable
를 사용하여 구성합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd' ;import { useRecoilState } from 'recoil' ;import styled from 'styled-components' ;import { toDoState } from './atoms' ;const Wrapper = styled.div` display: flex; max-width: 480px; width: 100%; margin: 0 auto; justify-content: center; align-items: center; height: 100vh; ` ;const Boards = styled.div` display: grid; width: 100%; grid-template-columns: repeat(3, 1fr); ` ;const Board = styled.div` padding: 20px 10px; padding-top: 30px; background-color: gray; border-radius: 5px; min-height: 200px; ` ;const Card = styled.div` border-radius: 5px; margin-bottom: 5px; padding: 10px 10px; background-color: white; ` ;function App ( ) { const [toDos, setToDos] = useRecoilState(toDoState); const onDragEnd = ({ draggableId, destination, source }: DropResult ) => { if (!destination) return ; setToDos((oldToDos ) => { const copyToDos = [...oldToDos]; copyToDos.splice(source.index, 1 ); copyToDos.splice(destination?.index, 0 , draggableId); return copyToDos; }); }; return ( <DragDropContext onDragEnd={onDragEnd}> <Wrapper> <Boards> <Droppable droppableId="one" > {(provided ) => ( <Board ref={provided.innerRef} {...provided.droppableProps}> {toDos.map((toDo, index ) => ( <Draggable key={toDo} draggableId={toDo} index={index}> {(provided ) => ( <Card ref={provided.innerRef} {...provided.dragHandleProps} {...provided.draggableProps}> {toDo} </Card> )} </ Draggable> ))} {provided.placeholder} </Board> )} </ Droppable> </Boards> </ Wrapper> </DragDropContext> ); } export default App;
Draggable
의 draggableProps
는 모든 영역을 dragHandleProps
는 특정 영역을 통해서만 드래그할 수 있도록 설정할 수 있습니다.
Draggable
list를 렌더링 하는 경우 각 Draggable
에 key prop을 추가하는 것이 중요합니다. key는 list 내에서 고유해야 합니다. key에 item의 index가 포함되어서는 안 되기 때문에 일반적으로 draggableId를 key로 사용합니다.
참고