[React] 画像ファイルをドラッグ&ドロップで取得してみる | 心を無にして始める React
準備
react-dropzone を使っていきます。
https://react-dropzone.js.org/
react-dropzone のインストール
npm install react-dropzone
ドラッグ&ドロップでファイルを表示する
今回は複数ファイル(3つまで)のファイルをD&Dで受け取って、表示できるようにしてみます。
まずは D&D でファイルを受け取れるコンポーネントを作ります。
場所はこれまでと同じように components 配下にします。
名前は Dropzone で作っていきます。
import { useEffect } from 'react';
import { useMemo } from 'react';
import { useDropzone } from 'react-dropzone';
const baseStyle = {
cursor: 'auto',
flex: 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
borderWidth: 2,
borderRadius: 2,
borderColor: '#eeeeee',
borderStyle: 'dashed',
backgroundColor: '#fafafa',
color: '#bdbdbd',
outline: 'none',
transition: 'border .24s ease-in-out'
};
const focusedStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
const DropZone = (props) => {
const {
onDrop,
children,
...other
} = props;
const {
acceptedFiles,
getRootProps,
getInputProps,
isFocused,
isDragAccept,
isDragReject
} = useDropzone({ accept: 'image/*', noClick: true, maxFiles: 3 });
useEffect(() => {
if (acceptedFiles.length) {
onDrop && onDrop(acceptedFiles);
}
}, [acceptedFiles]);
const style = useMemo(() => ({
...baseStyle,
...(isFocused ? focusedStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isFocused,
isDragAccept,
isDragReject
]);
return (
<div className="container" {...other}>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
{children}
</div>
</div>
);
}
export default DropZone;
次に App.js を変更して、表示してみます。
import React, { useState } from 'react';
import './App.css';
import Dropzone from "./components/DropZone";
function App() {
const [urls, setUrls] = useState([]);
const onDrop = (acceptedFiles) => {
console.log(acceptedFiles)
if (acceptedFiles) {
setUrls(acceptedFiles.map(acceptedFile => URL.createObjectURL(acceptedFile)))
}
}
return (
<>
<div className="bg-dark p-5" style={{ minHeight: '100vh' }}>
<Dropzone className="w-100" onDrop={onDrop}>
<div className="d-flex justify-content-center align-items-center p-5">
{
urls.length === 0 && (
<span>ファイルをドロップしてください</span>
)
}
{
urls.map(url => (
<div key={url?.toString()} className="border border-dark m-2">
<img src={url} alt="" style={{ maxWidth: 320, maxHeight: 240 }} />
</div>
))
}
</div>
</Dropzone>
</div>
</>
);
}
export default App;
動かしてみます。
はい、できました。