728x90

Dropzone이란 라이브러리가 존재하고, 이를 React hook방식으로 사용하도록 만든 것이 react-dropzone이다.

설치

npm install --save react-dropzone
yarn add react-dropzone
### 목적
프리뷰가 있고, Drop한 이미지를 삭제할 수 있어야한다.

먼저 react-dropzone의 Preview 코드를 가져온다.

import React, {useEffect, useState} from 'react';
import {useDropzone} from 'react-dropzone';

const thumbsContainer = {
  display: 'flex',
  flexDirection: 'row',
  flexWrap: 'wrap',
  marginTop: 16
};

const thumb = {
  display: 'inline-flex',
  borderRadius: 2,
  border: '1px solid #eaeaea',
  marginBottom: 8,
  marginRight: 8,
  width: 100,
  height: 100,
  padding: 4,
  boxSizing: 'border-box'
};

const thumbInner = {
  display: 'flex',
  minWidth: 0,
  overflow: 'hidden'
};

const img = {
  display: 'block',
  width: 'auto',
  height: '100%'
};


function Previews(props) {
  const [files, setFiles] = useState([]);
  const {getRootProps, getInputProps} = useDropzone({
    accept: {
      'image/*': []
    },
    onDrop: acceptedFiles => {
      setFiles(acceptedFiles.map(file => Object.assign(file, {
        preview: URL.createObjectURL(file)
      })));
    }
  });
  
  const thumbs = files.map(file => (
    <div style={thumb} key={file.name}>
      <div style={thumbInner}>
        <img
          src={file.preview}
          style={img}
          // Revoke data uri after image is loaded
          onLoad={() => { URL.revokeObjectURL(file.preview) }}
        />
      </div>
    </div>
  ));

  useEffect(() => {
    // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
    return () => files.forEach(file => URL.revokeObjectURL(file.preview));
  }, []);

  return (
    <section className="container">
      <div {...getRootProps({className: 'dropzone'})}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
      <aside style={thumbsContainer}>
        {thumbs}
      </aside>
    </section>
  );
}

<Previews />

하나의 파일만 받아오려면 옵션을 넣어야 한다.

const {
        getRootProps,
        getInputProps,
        isFocused,
        isDragAccept,
        isDragReject,
    } = useDropzone({
        onDrop: acceptedFiles => {
            setFiles(acceptedFiles.map(file => Object.assign(file, {
                preview: URL.createObjectURL(file)
            })))
        }, accept: { 'image/*': [], multiple: false }
    });

mutiple: false란 옵션을 이용하면 된다.

### 올린 파일 삭제

제일 어려웠던 부분은 올린 파일을 삭제하는 방법이었다.

파일을 어떻게 삭제할까?

<aside style={thumbsContainer} onClick={() => setFiles([])} >
                    {files.map(file => (
                        <div>
                            <div style={thumb} key={file.name}>
                            <div style={thumbInner}>
                                <img
                                    src={file.preview}
                                    style={img}
                                    // Revoke data uri after image is loaded
                                    onLoad={() => { URL.revokeObjectURL(file.preview) }}
                                    alt="preview"
                                />
                            </div>
                        </div>
                            <div>{file.path}</div>
                        </div>
                    ))
              }
</aside>

파일의 내용을 보여주는 코드에 onClick을 달아 state를 초기화하는 방법이다.

또는 여러개의 파일을 사용한다면, setFiles( files.filter( f => ) )방법으로 하면 된다.

반응형

+ Recent posts