ドロップゾーン

1import classNames from 'classnames';
2import React, { useCallback, useState } from 'react';
3import { useDropzone } from 'react-dropzone';
4import { HiPhotograph } from 'react-icons/hi';
5
6const Dropzone = () => {
7  const [preview, setPreview] = useState<string>();
8
9  const onDropAccepted = useCallback((acceptedFiles: File[]) => {
10    const file = acceptedFiles[0] as File;
11    const reader = new FileReader();
12
13    reader.addEventListener('load', () => {
14      setPreview(reader.result as string);
15    });
16
17    reader.readAsDataURL(file);
18  }, []);
19  const { getRootProps, getInputProps, isDragActive, isDragAccept } =
20    useDropzone({
21      onDropAccepted,
22      accept: {
23        'image/jpeg': [],
24        'image/png': [],
25      },
26    });
27
28  const isActive = isDragActive && isDragAccept;
29
30  return (
31    <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
32      <div
33        {...getRootProps()}
34        className={classNames(
35          'rounded-md border-dashed border-2 border-gray-500 flex transition-colors items-center justify-center aspect-square',
36          isActive && 'border-pink-600'
37        )}
38      >
39        <input {...getInputProps()} />
40        <div>
41          <HiPhotograph
42            size={80}
43            className={classNames(
44              'mx-auto mb-2',
45              isActive ? 'text-pink-600' : 'opacity-40'
46            )}
47          />
48          <p className={isActive ? 'text-pink-600' : 'opacity-60'}>
49            {isActive ? 'はなしてください' : '画像をドロップしてください'}
50          </p>
51        </div>
52      </div>
53      <div>{preview && <img src={preview} alt="" />}</div>
54    </div>
55  );
56};
57
58export default Dropzone;

使用ライブラリ

参考サイト