昨今のWEBアプリでアップロードを行う場合、通常のファイル選択(<input type="file"/>
)に加えて、エクスプローラからのドラッグ&ドロップに対応している事が多い。
というわけで本記事では、Reactで汎用的に使えるファイル選択&ドロップ部品を作るサンプルコードを紹介します。
スポンサーリンク
完成イメージ
上のように、通常のファイル選択と、点線の枠内にファイルをドロップできるコンポーネントとします。また、ファイルの単一選択 or 複数選択可をプロパティで指定可能にします。
サンプルコード
プロパティの定義
2つのプロパティを持ちます。
onChange
は、ファイルが選択された時に親コンポーネントに通知するためのイベントハンドラです。
multiple
は、複数選択を許可するかどうかのフラグです。
/**
* プロパティ
*/
interface FileDropzoneProp {
/**
* ファイル選択時のイベント
*/
onChange: (files: FileList) => void,
/**
* 複数ファイル選択を許可するか
*/
multiple?: boolean
}
コンポーネント本体
import React, { ChangeEvent, DragEvent, useCallback, useRef, useState } from 'react'
import style from './Style.module.css';
/**
* ファイルドロップコンポーネント
*/
function FileDropzone({
onChange,
multiple
}: FileDropzoneProp) {
const [dragging, setDragging] = useState(false)
const refFileElement = useRef<HTMLInputElement>(null)
/**
* ドロップ時の処理
*/
const handleDrop = useCallback(
async (e: React.DragEvent<HTMLDivElement>) => {
e.stopPropagation()
e.preventDefault()
if (e.dataTransfer.files?.length > 0 && refFileElement.current) {
if (multiple) {
refFileElement.current.files = e.dataTransfer.files
} else {
const dt = new DataTransfer()
dt.items.add(e.dataTransfer.files[0])
refFileElement.current.files = dt.files
}
onChange(refFileElement.current.files)
}
setDragging(false)
},
[onChange])
/**
* ファイル選択(input type="file"からの選択)
*/
const handleChange = useCallback(
async (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
onChange(e.target.files)
}
},
[onChange])
/**
* Dragover or Dragleave
* @param e
*/
const handleDragoverOrLeave = useCallback((e: DragEvent<HTMLDivElement>) => {
e.stopPropagation()
e.preventDefault()
setDragging(e.type === "dragover")
}, []);
return (
<div
className={`${style.dragzone} ${dragging ? style.dragging : ""}`}
onDragOver={handleDragoverOrLeave}
onDragLeave={handleDragoverOrLeave}
onDrop={handleDrop}>
ここにファイルをドロップ<br />
または<br />
<input
ref={refFileElement}
onChange={handleChange}
type="file"
multiple={multiple}/>
</div>
)
}
export default FileDropzone
CSS
念の為他のスタイルに影響が出ないように、CSSモジュールとして作る。
ファイル名は Style.module.css
とする。
/** ドラッグエリア */
.dragzone {
padding: 2rem;
background: #eee;
border: 5px dashed #999;
color: #555;
text-align: center;
}
/** ドラッグ中の状態 */
.dragging {
background: #ddd;
}
スポンサーリンク
使用方法
配置はインポートして置くだけ。
ファイルが選択されたときのイベントは onChange
で受け取り、イベントの引数に選択されたファイルが配列(FIleList
型)で渡される。
<FileDropzone onChange={files => {
console.log(files[0])
}} />
複数選択を可能にする場合、multiにtrue
を指定。
<FileDropzone multiple={true} onChange={files => {
for( let i = 0; i < files.length; i++) {
console.log(files[i])
}
}} />
まとめ
Reactでファイル選択&ドロップできる、汎用的に使えるコンポーネントのサンプルコードをしました。
もちろん自作などしなくても、ちょっと検索すれば、ファイル選択関連で npmでインストールできるコンポーネントは沢山ヒットする。ただ、見た目や操作性をこだわりたいのであれば、自前で作るのもありだろう。
0 件のコメント:
コメントを投稿