프로젝트 진행중에, 이미지를 업로드할때 드래그 앤 드랍을 이용해서 이미지 업로드 하는 기능을 구현하고 싶었다.
드래그 앤 드랍을 구현하려면 drag 관련 이벤트 속성을 알아두는 것이 필요하다.
export default function Component() {
const [dragging, setDragging] = useState(false);
const [file, setFile] = useState<File | null>(null);
const [previewUrl, setPreviewUrl] = useState<string | null | undefined>();
useEffect(() => {
if (!file) {
return;
}
const fileReader = new FileReader();
fileReader.onload = () => {
if (typeof fileReader.result === "string") {
setPreviewUrl(fileReader.result);
}
};
fileReader.readAsDataURL(file);
}, [file]);
const onDragEnterHandler = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setDragging(true);
};
const onDragLeaveHandler = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setDragging(false);
};
const onDragOverHandler = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
if (e.dataTransfer.files) {
setDragging(true);
}
};
const onDropHandler = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setDragging(false);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
setFile(e.dataTransfer.files[0]);
e.dataTransfer.clearData();
}
};
<div
className={
dragging
? `${classes.image_input_container} ${classes.dragging}`
: classes.image_input_container
}
onDragEnter={onDragEnterHandler}
onDragLeave={onDragLeaveHandler}
onDragOver={onDragOverHandler}
onDrop={onDropHandler}
>
{!previewUrl && (
<>
<input
required
type={"file"}
accept={".svg"}
className={classes.image_input}
multiple={false}
aria-hidden
id="image_upload"
/>
<div className={classes.icon_container}>
<BsFillImageFill />
</div>
<label
htmlFor="image_upload"
className={classes.image_input_label}
>
이미지 가져오기
</label>
</>
)}
{previewUrl && (
<Image
src={previewUrl}
width={300}
height={300}
alt="image"
className={classes.preview_image}
/>
)}
</div>
input 부분을 숨겨주고, 이미지가 업로드될때, previewUrl에 파일 경로를 담아줌으로써
이미지가 나타나도록 했다.