ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] react-beautiful-dnd 으로 요소 드래그 되도록 만들기 2
    WEB Dev/Javascript | REACT | Node.js 2022. 4. 4. 00:08
    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

    댓글

Designed by Tistory.