모든 HTMLElement 상속 요소는 draggable 이라는 boolean 타입 속성을 제공한다.
<h1 draggable>Drag Me</h1>
이 드래그 앤 드롭과 관련된 이벤트 핸들러들은 DragEvent 타입을 매개변수의 타입으로 사용한다.
이 DragEvent 타입은 리액트에서 제공하는 타입이다.
interface DragEvent<T = Element> extends MouseEvent<T, NativeDragEvent> {
dataTransfer: DataTransfer;
}
딱 봐도 dataTransfer
속성이 핵심이다.
interface DataTransfer {
dropEffect: "none" | "copy" | "link" | "move";
effectAllowed: "none" | "copy" | "copyLink" | "copyMove" | "link" | "linkMove" | "move" | "all" | "uninitialized";
readonly files: FileList;
readonly items: DataTransferItemList;
readonly types: ReadonlyArray<string>;
clearData(format?: string): void;
getData(format: string): string;
setData(format: string, data: string): void;
setDragImage(image: Element, x: number, y: number): void;
}
files
속성으로 드롭한 파일의 정보를 알 수 있다.
웹 브라우저는 기본으로 drop 이벤트가 발생하지 않도록 설계되어있다.
이에 따라 drop 이벤트가 발생하기 위해서는 dragover 이벤트 핸들러에서 preventDefault
메서드를 호출해야 한다.
const onDragOver = (e:DragEvent) =>{
e.preventDefault()
}
또한 onDrop 이벤트 핸들러에도 preventDefault
메서드를 호출하는 것이 좋다.
웹 브라우저는 기본으로 파일을 드롭할 때 드롭한 파일을 새로운 창을 열어 보여주기 때문이다.
const onDrop = (e:DragEvent) =>{
e.preventDefault()
}
import React,{DragEvent} from 'react'
const DragDrop = () => {
const onDragStart =(e:DragEvent) =>{
console.log(e.dataTransfer);
}
const onDragEnter =(e:DragEvent) =>{
console.log(e.dataTransfer);
}
const onDragOver = (e:DragEvent) =>{
e.preventDefault()
}
const onDrop = (e:DragEvent) =>{
e.preventDefault()
console.log(e.dataTransfer);
}
return <div><p>DragDrop</p>
<div draggable onDragStart={onDragStart} onDragEnter={onDragEnter}>
<h1>Drag Me</h1>
</div>
<div onDrop={onDrop} onDragOver={onDragOver}>
<h1>Drop Over Me</h1>
</div>
</div>
}
import React, {DragEvent} from 'react'
const FileDrop = () => {
const onDragOver = (e:DragEvent) => e.preventDefault()
const onDrop = (e:DragEvent)=>{
e.preventDefault()
const files = e.dataTransfer.files
for(let i = 0; i < files.length; i++){
const file = files[i];
console.log(file)
}
}
return (
<div>
<p>FileDrop</p>
<div onDrop={onDrop} onDragOver={onDragOver}>
<h1>Drop Image Files Over Me</h1>
</div>
</div>
)
}