[React] react-beautiful-dnd 으로 요소 드래그 되도록 만들기 2

2022. 4. 4. 00:08WEB Dev/Javascript | REACT | Node.js

728x90

 

 

Goal 컴포넌트를 드래그 할 수 있도록 만들었다.

이제 그 내부의 Todo 부분을 드래그 할 수 있도록 해야하는데 내부도 Droppable 영역으로 지정해야 하기 때문에

Droppable 태그를 넣어준다.

 

 

 

 

위와 같은 순서가 될 것이다.

 

 

이번에 리턴해 줄 Todo 는 Goal 안에서 map으로 돌고 있는 컴포넌트다.

아래와 같이 생겼다.

 

 

return (
    <div className="goals-list-box" key={data.goalOrderNo}>
      {/* Goal 컴포넌트 시작 */}
      <Button className="goals-list-button" data-index={index} data={data}>
        <ReceiptIcon className="goals-list-icon" />
        <div className="goals-list-text" id={data.goalOrderNo} name={data.goalOrderNo} 
        style={{ color: data.goalTitleColor }}>
          <p>{data.goalTitle}</p>
        </div>
        <p className="goals-list-plus-icon-wrap">
          <AddCircleIcon className="goals-list-plus-icon" />
        </p>
      </Button>
      {/* Goal 컴포넌트 종료 */}
      {/* Todo 컴포넌트 map 시작 */}
      <div className="todos-list-wrap">
        {data.todos.map((data, idx) => {
          return (
            <div key={data.todoId}>
              <FeedTodoData todos={data} index={idx}/> 
            </div>
          );
        })}
      </div>
      {/* Todo 컴포넌트 map 종료 */}
    </div>
  );

 

 

 

 

현재 Goal 컴포넌트가 드래그 되고 있고 이번에는 이 내부의 Todo 컴포넌트에 드래그를 넣어줘야 한다.

그렇기 때문에 각 Todo에게는 Goal 컴포넌트가 하나의 Droppable 구역이 된다. 

 

 

1. DragDropContext로 감싸기

 

 

해당 컴포넌트 전체를 우선 DropDragContext로 감싸주자. 임시로 onDragEnd 도 만들어준다.

 

 

 /* 함수 선언 시작 */

  const onDragEnd = () => {
    console.log("드래그")
  }

  /* 함수 선언 종료 */

  return (
    <DragDropContext onDragEnd={onDragEnd}>
    <div className="goals-list-box" key={data.goalOrderNo}>
      {/* Goal 컴포넌트 시작 */}
      <Button className="goals-list-button" data-index={index} data={data}>
        <ReceiptIcon className="goals-list-icon" />
        <div className="goals-list-text" id={data.goalOrderNo} name={data.goalOrderNo} 
        style={{ color: data.goalTitleColor }}>
          <p>{data.goalTitle}</p>
        </div>
        <p className="goals-list-plus-icon-wrap">
          <AddCircleIcon className="goals-list-plus-icon" />
        </p>
      </Button>
      {/* Goal 컴포넌트 종료 */}
      {/* Todo 컴포넌트 map 시작 */}
      <div className="todos-list-wrap">
        {data.todos.map((data, idx) => {
          return (
            <div key={data.todoId}>
              <FeedTodoData todos={data} index={idx}/> 
            </div>
          );
        })}
      </div>
      {/* Todo 컴포넌트 map 종료 */}
    </div>
    </DragDropContext>
  );

 

 

2. Droppble 로 감싸기

 

 

그리고 내부에 Droppable을 넣어준다.

 

 

  /* 함수 선언 시작 */

  const onDragEnd = () => {
    console.log("드래그")
  }

  /* 함수 선언 종료 */

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="Goal">
        <div className="goals-list-box" key={data.goalOrderNo}>
          {/* Goal 컴포넌트 시작 */}
          <Button className="goals-list-button" data-index={index} data={data}>
            <ReceiptIcon className="goals-list-icon" />
            <div className="goals-list-text" id={data.goalOrderNo} name={data.goalOrderNo} 
            style={{ color: data.goalTitleColor }}>
              <p>{data.goalTitle}</p>
            </div>
            <p className="goals-list-plus-icon-wrap">
              <AddCircleIcon className="goals-list-plus-icon" />
            </p>
          </Button>
          {/* Goal 컴포넌트 종료 */}
          {/* Todo 컴포넌트 map 시작 */}
          <div className="todos-list-wrap">
            {data.todos.map((data, idx) => {
              return (
                <div key={data.todoId}>
                  <FeedTodoData todos={data} index={idx}/> 
                </div>
              );
            })}
          </div>
          {/* Todo 컴포넌트 map 종료 */}
        </div>
      </Droppable>
    </DragDropContext>
  );

 

 

그리고 provided를 적용해준다.

 

  /* 함수 선언 시작 */

  const onDragEnd = () => {
    console.log("드래그")
  }

  /* 함수 선언 종료 */

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="Goal">
      {provided =>  (
        <div className="goals-list-box" key={data.goalOrderNo}>
          {/* Goal 컴포넌트 시작 */}
          <Button className="goals-list-button" data-index={index} data={data}>
            <ReceiptIcon className="goals-list-icon" />
            <div className="goals-list-text" id={data.goalOrderNo} name={data.goalOrderNo} 
            style={{ color: data.goalTitleColor }}>
              <p>{data.goalTitle}</p>
            </div>
            <p className="goals-list-plus-icon-wrap">
              <AddCircleIcon className="goals-list-plus-icon" />
            </p>
          </Button>
          {/* Goal 컴포넌트 종료 */}
          {/* Todo 컴포넌트 map 시작 */}
          <div className="todos-list-wrap">
            {data.todos.map((data, idx) => {
              return (
                <div key={data.todoId}>
                  <FeedTodoData todos={data} index={idx}/> 
                </div>
              );
            })}
          </div>
          {/* Todo 컴포넌트 map 종료 */}
        </div>
      )}
      </Droppable>
    </DragDropContext>
  );

 

 

첫번째 div에 ref={provded.innerRef} {...provided.droppableProps} 를 넣어준다.

 

 

  /* 함수 선언 시작 */

  const onDragEnd = () => {
    console.log("드래그")
  }

  /* 함수 선언 종료 */

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="Goal">
      {provided =>  (
        <div className="goals-list-box" key={data.goalOrderNo}
        ref={provided.innerRef} {...provided.droppableProps}>
          {/* Goal 컴포넌트 시작 */}
          <Button className="goals-list-button" data-index={index} data={data}>
            <ReceiptIcon className="goals-list-icon" />
            <div className="goals-list-text" id={data.goalOrderNo} name={data.goalOrderNo} 
            style={{ color: data.goalTitleColor }}>
              <p>{data.goalTitle}</p>
            </div>
            <p className="goals-list-plus-icon-wrap">
              <AddCircleIcon className="goals-list-plus-icon" />
            </p>
          </Button>
          {/* Goal 컴포넌트 종료 */}
          {/* Todo 컴포넌트 map 시작 */}
          <div className="todos-list-wrap">
            {data.todos.map((data, idx) => {
              return (
                <div key={data.todoId}>
                  <FeedTodoData todos={data} index={idx}/> 
                </div>
              );
            })}
          </div>
          {/* Todo 컴포넌트 map 종료 */}
        </div>
      )}
      </Droppable>
    </DragDropContext>
  );

 

그리고 잊지 말고 {provided.placeholder} 를 넣어야 한다.

표시된 {/* Todo 컴포넌트 map 종료 */} 부분 하단에 {provided.placeholder} 를 넣어줘야 한다.

 

 

 

그리고 이제 실제로 드래그 하는 부분에 Draggable을 넣어준다.

 

 

3. Draggable 적용하기

 

 

 return (
    <div key={data.todoId}>
      <FeedTodoData todos={data} index={idx}/> 
    </div>
  );

 

 

여기가 실제로 드래그가 되야 하는 부분이고 여기에 Draggable을 감싸준다.

 

 return (
 <Draggable>
    <div key={data.todoId}>
      <FeedTodoData todos={data} index={idx}/> 
    </div>
 </Draggable>
  );

 

 

그리고 draggableId도 만들어준다. 위에서 Srting(index)는 이미 썼으니 Todo 를 더해서 string화 시켜보자.

또 provided 값을 준다.

 

 

return (
    <Draggable draggableId={"todo" + index} index={index}>
      {provided => (
        <div key={data.todoId}>
          <FeedTodoData todos={data} index={index}/> 
        </div>
     )}
    </Draggable>
);

 

 

그리고 map 으로 return 되는 가장 첫번째 태그가 Draggable이 되었기 때문에 Draggable에 key 값을 주고 

실제 클릭해야하는 div에게 ref={provided.innerRef}, {...provided.draggableProps}, {...provided.dragHandleProps} 를 넣어준다.

 

 

 return (
    <Draggable draggableId={"todo" + index} index={index} key={data.todoId}>
      {provided => (
        <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} >
          <FeedTodoData todos={data} index={index}/> 
        </div>
     )}
    </Draggable>
);

 

 

 

 

 

 

 

 

와~ 또 굴러가유~

 

 

하지만 이제 onDragEnd 함수를 만들어야 한다 ~(>_<。)

 

728x90