[Next.js] 드래그 상태에서 css 조작하기
본문 바로가기
더 알아보기/기능

[Next.js] 드래그 상태에서 css 조작하기

by 은돌1113 2023. 11. 23.

관련 글 목차

1️⃣ react-beautiful-dnd를 사용하여 드래그로 순서 변경하기

 

[React, Next.js] react-beautiful-dnd를 사용하여 드래그로 순서 변경하기

라이브러리는 react-beautiful-dnd npm 사이트에서 가져와서 사용했다. react-beautiful-dnd Beautiful and accessible drag and drop for lists with React. Latest version: 13.1.0, last published: a year ago. Start using react-beautiful-dnd in yo

eundol1113.tistory.com

2️⃣ 다중 이미지 업로드 및 미리 보기 + 드래그로 순서 변경

 

[Next.js] 다중 이미지 업로드 및 미리보기 + 드래그로 순서 변경

[React, Next.js] react-beautiful-dnd를 사용하여 드래그로 순서 변경하기 라이브러리는 react-beautiful-dnd npm 사이트에서 가져와서 사용했다. react-beautiful-dnd Beautiful and accessible drag and drop for lists with React. Lat

eundol1113.tistory.com

3️⃣ 수평 dnd 만들기

 

[Next.js] 수평 dnd 만들기

이전 게시물에서 구현했던 dnd는 수직으로 정렬 되어 있어서 단순히 display: flex 설정만 해주면 동작 하겠지 했는 데 [Next.js] 다중 이미지 업로드 및 미리보기 + 드래그로 순서 변경 [React, Next.js] reac

eundol1113.tistory.com


들어가며

이번 글은 제목처럼 "드래그 상태에서 css 조작하기"에 관한 글입니다.

 

적용 전

 

🚀 적용 후

 

위 예시는 테스트용으로 작성한 코드 실행 화면입니다. (참고용)

 

table 태그를 사용하여 구현하였더니 tr에 너비가 동일하지 않아서 그 부분은 감안하고 참고해주세요.


적용 코드

1탄에서 사용했던 코드에서 빨간색 선으로 표시한 부분이 추가되었고,

 

여기서 주의해야 할 부분은 ⭐ style 속성에... provided.draggableProps.style이 드래그 중에 변경되는 스타일을 관리하고, 드래그가 끝났을 때 해당 스타일을 초기화하는 역할을 하기 때문에 해당 코드 아래에 드래그 중에 적용하고 싶은 코드를 작성해야 한다.

더보기
// React 관련 요소
import { useEffect, useRef, useState } from "react"

// 드래그 요소
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"
// 스타일 정의
import styled from "styled-components"

const DragContent = styled.div`
  border: 1px solid lightgrey;
`

const DragLand = () => {
  // window가 로드 된 시점에서 렌더링
  const [winReady, setwinReady] = useState(false)

  useEffect(() => {
    setwinReady(true)
  }, [])

  return (
    <>
      {/* 윈도우, DOM 로드 시점에서 드래그 생성 */}
      {winReady ? <Drag /> : null}
    </>
  )
}

// 드래그 요소 생성
export const Drag = () => {
  const [todos, setTodos] = useState([
    { id: "1", title: "공부" },
    { id: "2", title: "헬스" },
    { id: "3", title: "독서" },
    { id: "4", title: "산책" },
    { id: "5", title: "요리" },
  ])

  const tbodyRef = useRef(null)

  const [tbodyWidth, setTbodyWidth] = useState("100%")

  useEffect(() => {
    if (tbodyRef.current) {
      const width = tbodyRef.current.offsetWidth
      setTbodyWidth(`${width}px`)
    }
  }, [todos])

  const handleChange = (result) => {
    if (!result.destination) return
    console.log(result)
    const items = [...todos]
    const [reorderedItem] = items.splice(result.source.index, 1)
    items.splice(result.destination.index, 0, reorderedItem)

    setTodos(items)
  }

  return (
    <>
      {/* 드래그 영역 */}
      <DragDropContext onDragEnd={handleChange}>
        {/* 드래그 놓을 수 있는 영역 */}
        <Droppable droppableId="DropLand">
          {/* 드래그 Div 생성 */}
          {(provided, snapshot) => (
            // CCS가 적용된 Div
            <DragContent
              {...provided.droppableProps}
              ref={(el) => {
                provided.innerRef(el)
                tbodyRef.current = el
              }}
            >
              {todos.map((data, index) => (
                <Draggable key={data.id} draggableId={data.id} index={index}>
                  {(provided, snapshot) => (
                    <Content
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      style={{
                        ...provided.draggableProps.style, // 드래그 중에 변경되는 스타일을 관리하고, 드래그가 끝났을 때 해당 스타일을 초기화 해준다.
                        width: tbodyWidth,
                        justifyContent: "space-around",
                      }}
                    >
                      {data.title}
                    </Content>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </DragContent>
          )}
        </Droppable>
      </DragDropContext>
    </>
  )
}

const Content = styled.div`
  margin: 8px;
  padding: 10px;
  border: 1px solid lightgrey;
  background: aliceblue;
  border-radius: 2px;
`

export default DragLand

댓글