Drag-n-drop загрузчик файлов в React

react-dropzone – это совместимый с HTML5 компонент React для обработки перетаскивания файлов.

HTML5 поддерживает загрузку файлов через <input type=”file” />. Компонент react-dropzone предоставляет дополнительные функции, среди которых настройка области перетаскивания, предварительный просмотр и ограничение типа и количества файлов.

В этом руководстве вы узнаете, как добавить response-dropzone в свой проект React, и изучите некоторые из предоставляемых им базовых функций.

Требования

Для выполнения этого урока вам понадобится локальная установка Node.js. Следуйте инструкциям для вашего дистрибутива: mac OSUbuntuDebianCentOS.

Руководство было проверено на версиях Node v15.3.0, npm v7.4.0, react v17.0.1 и react-dropzone v11.2.4.

1: Создание тестового проекта

Начнем с создания простого проекта. С помощью create-react-app сгенерируйте приложение React.

npx create-react-app react-dropzone-example

Перейдите в новый каталог:

cd react-dropzone-example

Установите react-dropzone:

npm install react-dropzone@11.2.4

Теперь у вас есть новый проект React с компонентом react-dropzone.

2: Добавление компонента Dropzone

У response-dropzone есть стандартные настройки, которые позволяют добавлять его в приложения при помощи минимальной конфигурации.

Как минимум, вам понадобится свойство onDrop, которое будет обрабатывать перетаскиваемые в область файлы и базовый текст с призывом к действию, чтобы помочь пользователю разобраться. В файл src/DropzoneComponent.js добавьте:

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

function DropzoneComponent() {
  const onDrop = useCallback(acceptedFiles => {
    console.log(acceptedFiles);
  }, []);

  const {
    getRootProps,
    getInputProps
  } = useDropzone({
    onDrop
  });

  return (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      <div>Drag and drop your images here.</div>
    </div>
  )
}

export default DropzoneComponent;

Этот код обеспечивает обработку перетаскивания файлов в вашем приложении.

Примечание: Стоит отметить, что, хотя зона response-dropzone и предназначена для перетаскивания файлов, по умолчанию она принимает события клика, которые запускают диалоговое окно для выбора файлов.

Добавьте этот компонент в свое приложение React (файл src/App.js):

import DropzoneComponent from './DropzoneComponent';

function App() {
  return (
    <div className="App">
      <DropzoneComponent />
    </div>
  );
}

export default App;

Запустите приложение и понаблюдайте за ним в веб-браузере. Вы должны увидеть элемент div с текстом:

Drag and drop your images here

Попробуйте перетащить разные файлы в компонент Dropzone. В настоящее время для отображения файлов код использует console.log. Информация из загруженных файлов включает имя, дату последнего изменения, размер и тип (name, lastModified, size, and type).

На данный момент у нас есть рабочий компонент React Dropzone с конфигурацией по умолчанию. Дополнительные параметры конфигурации можно найти в документации response-dropzone.

3: Стилизация компонента Dropzone

По умолчанию зона сброса response-dropzone не оформлена. В документации представлены стили для общего оформления этой зоны, где используется комбинация гибкого блока и пунктирных границ, которая указывает пользователям на область для перетаскивания файлов.

Также response-dropzone поддерживает свойства для ситуаций, когда с компонентом активно взаимодействуют (isDragActive), компонент принимает (isDragAccept) или отклоняет файл (isDragReject).

Пересмотрите свой DropzoneComponent и добавьте isDragActive, isDragAccept и isDragReject, которые будут применяться к типам файлов JPEG и PNG:

import React, { useCallback, useMemo } from 'react';
import { useDropzone } from 'react-dropzone';

const baseStyle = {
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  padding: '20px',
  borderWidth: 2,
  borderRadius: 2,
  borderColor: '#eeeeee',
  borderStyle: 'dashed',
  backgroundColor: '#fafafa',
  color: '#bdbdbd',
  transition: 'border .3s ease-in-out'
};

const activeStyle = {
  borderColor: '#2196f3'
};

const acceptStyle = {
  borderColor: '#00e676'
};

const rejectStyle = {
  borderColor: '#ff1744'
};

function DropzoneComponent(props) {
  const onDrop = useCallback(acceptedFiles => {
    console.log(acceptedFiles);
  }, []);

  const {
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject
  } = useDropzone({
    onDrop,
    accept: 'image/jpeg, image/png'
  });

  const style = useMemo(() => ({
    ...baseStyle,
    ...(isDragActive ? activeStyle : {}),
    ...(isDragAccept ? acceptStyle : {}),
    ...(isDragReject ? rejectStyle : {})
  }), [
    isDragActive,
    isDragReject,
    isDragAccept
  ]);

  return (
    <div {...getRootProps({style})}>
      <input {...getInputProps()} />
      <div>Drag and drop your images here.</div>
    </div>
  )
}

export default DropzoneComponent;

В результате у вас будет стандартная зона для перетаскивания файлов, отмеченная пунктирной линией по периметру.

Зона сброса с поддержкой свойств isDragActive, isDragAccept и isDragReject предоставит пользователю обратную связь о том, действителен ли его файл.

4: Добавление превью изображений

Предварительный просмотр – это копия изображения, которое перетаскивается в зону сброса. Благодаря этому пользователи получают визуальную обратную связь и могут сразу проверить, правильные ли изображения они добавили.

Предварительный просмотр был удален в версии 7.0.0, однако документация предоставляет альтернативный способ добавить предпросмотр – с помощью комбинации Object.assign() и URL.createObjectURL().

Вернитесь к своему компоненту src/DropzoneComponent.js и добавьте предварительный просмотр:

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

const baseStyle = {
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  padding: '20px',
  borderWidth: 2,
  borderRadius: 2,
  borderColor: '#eeeeee',
  borderStyle: 'dashed',
  backgroundColor: '#fafafa',
  color: '#bdbdbd',
  transition: 'border .3s ease-in-out'
};

const activeStyle = {
  borderColor: '#2196f3'
};

const acceptStyle = {
  borderColor: '#00e676'
};

const rejectStyle = {
  borderColor: '#ff1744'
};

function DropzoneComponent(props) {
  const [files, setFiles] = useState([]);

  const onDrop = useCallback(acceptedFiles => {
    setFiles(acceptedFiles.map(file => Object.assign(file, {
      preview: URL.createObjectURL(file)
    })));
  }, []);

  const {
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject
  } = useDropzone({
    onDrop,
    accept: 'image/jpeg, image/png'
  });

  const style = useMemo(() => ({
    ...baseStyle,
    ...(isDragActive ? activeStyle : {}),
    ...(isDragAccept ? acceptStyle : {}),
    ...(isDragReject ? rejectStyle : {})
  }), [
    isDragActive,
    isDragReject,
    isDragAccept
  ]);

  const thumbs = files.map(file => (
    <div key={file.name}>
      <img
        src={file.preview}
        alt={file.name}
      />
    </div>
  ));

  // clean up
  useEffect(() => () => {
    files.forEach(file => URL.revokeObjectURL(file.preview));
  }, [files]);

  return (
    <section>
      <div {...getRootProps({style})}>
        <input {...getInputProps()} />
        <div>Drag and drop your images here.</div>
      </div>
      <aside>
        {thumbs}
      </aside>
    </section>
  )
}

export default DropzoneComponent;

Примечание: Чтобы избежать сохранения ненужных предварительных просмотров, нужно вызвать URL.revokeObjectURL(file.preview).

Теперь всякий раз, когда пользователь перетаскивает файл (или файлы) в зону сброса, на экране будет отображаться предварительный просмотр.

Заключение

В этом руководстве вы познакомились с функцией response-dropzone и узнали о том, как ее можно использовать в приложении React для расширения функций перетаскивания файлов.

Tags:

Добавить комментарий