drag drop 으로 이미지 순서 위치 변경하기

miin·2023년 10월 25일
0

Skill Collection [Function]

목록 보기
41/46
post-thumbnail
  • css draggable 사용
  const [enabled, setEnabled] = useState(false)

  const dragStartHandler = (e: React.DragEvent<HTMLDivElement>, id: number) => {
      e.dataTransfer.effectAllowed = 'move' // 2
      e.dataTransfer.setData('imgIndex', String(id)) // 3
    }
    const dragDrop = (e: React.DragEvent, index: number) => {
      e.preventDefault()
      const sourceIndex = Number(e.dataTransfer.getData('imgIndex'))
      if (sourceIndex === index) return
      const updateImages = [...imgListFile]
      const [movedImage] = updateImages.splice(sourceIndex, 1)
      updateImages.splice(index, 0, movedImage)
      setImgListFile(updateImages)
  }
  
    const allowDrop = (e: React.DragEvent) => {
    e.preventDefault()
  }
    
      useEffect(() => {
    const animation = requestAnimationFrame(() => setEnabled(true))

    return () => {
      cancelAnimationFrame(animation)
      setEnabled(false)
    }
  }, [])

  if (!enabled) {
    return null
  }

return(
{imgListFile?.map((list, i) => (
   <div
      style={{ position: 'relative' }}
       key={i}
       onDragOver={(e) => allowDrop(e)}
       onDrop={(e) => dragDrop(e, 0)}>
      <ImageStyle
        src={list}
        width={240}
        height={240}
        alt={`상품등록 추가이미지${i}`}
         draggable="true"
         onDragStart={(e) => dragStartHandler(e, i)}
         onDragOver={(e) => allowDrop(e)}
         onDrop={(e) => dragDrop(e, i)}
		/>
   </div>
   ))}  
)
  • react-beautiful-dnd 사용
interface DragDrop {
  imgList: string[]
  closeBtn: (i: number) => void
  setImgListFile: React.Dispatch<SetStateAction<string[]>>
  fileOnChange: (e: React.ChangeEvent<HTMLInputElement>, type: string) => void
}

import React, { SetStateAction, useEffect, useState } from 'react'
import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd'
import XIcon from 'src/assets/icon/common/ico_black_x_btn.svg'
import { styled } from 'styled-components'

const DragDrop = ({ imgList, closeBtn, setImgListFile, fileOnChange }: DragDrop) => {
  const [enabled, setEnabled] = useState(false)

  useEffect(() => {
    const animation = requestAnimationFrame(() => setEnabled(true))

    return () => {
      cancelAnimationFrame(animation)
      setEnabled(false)
    }
  }, [])

  if (!enabled) {
    return null
  }

  const onDragEnd = (result: DropResult) => {
    if (!result.destination) {
      return
    }

    const items = Array.from(imgList) // 원본 배열 복사
    const [removed] = items.splice(result.source.index, 1)

    items.splice(result.destination.index, 0, removed)
    setImgListFile(items)
  }

  return (
    <>
		<DragDropContext onDragEnd={onDragEnd}>
  			<Droppable
    			droppableId="droppable"
    			direction={imgList.length > 2 ? 'horizontal' : undefined}>
   				 {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.droppableProps}
                    style={{
                      display: 'flex',
                      gap: '16px',
                      flexWrap: 'wrap',
                      // minWidth: `${imgList.length * 230}px`,
                    }}
                  >
                {imgList.length > 0 && (
                  <>
              {imgList?.map((list, i) => (
                <Draggable key={i} draggableId={i.toString()} index={i}>
                  {(provided) => (
              <div
                ref={provided.innerRef}
                {...provided.draggableProps}
                {...provided.dragHandleProps}
                style={{
                  position: 'relative',
                  ...provided.draggableProps.style,
                }}
              >
                {provided?.placeholder}
                <ImageStyle
                  src={list}
                  width={240}
                  height={240}
                  alt={`상품등록 추가이미지${i}`}
                />
              <XIcon
                style={{
            position: 'absolute',
            top: '23px',
            right: '23px',
            cursor: 'pointer',
                }}
                onClick={() => closeBtn(i)}
              />
            </div>
                )}
              </Draggable>
           ))}
			)}
        </Droppable>
      </DragDropContext>
    </>
)

0개의 댓글