序章

react-dropzone は、ファイルのドラッグアンドドロップを処理するためのHTML5準拠のReactコンポーネントです。

HTML5は、を使用したファイルのアップロードをサポートしています。 react-dropzoneは、ドロップゾーンのカスタマイズ、プレビューの表示、ファイルの種類と量の制限などの追加機能を提供します。

注: ReactではなくVueを使用している場合は、vue-dropzoneのチュートリアルを参照してください。

このチュートリアルでは、Reactプロジェクトにreact-dropzoneを追加する方法を学び、Reactプロジェクトが提供する機能のいくつかを探ります。

前提条件

このチュートリアルを完了するには、次のものが必要です。

このチュートリアルは、ノードv15.3.0、npm v7.4.0、react v17.0.1、およびreact-dropzonev11.2.4で検証されました。

ステップ1—プロジェクトの設定

create-react-app を使用してReactアプリを生成し、依存関係をインストールすることから始めます。

  1. npx create-react-app react-dropzone-example

新しいプロジェクトディレクトリに移動します。

  1. cd react-dropzone-example

react-dropzoneをインストールします。

  1. npm install react-dropzone@11.2.4

この時点で、react-dropzoneを使用した新しいReactプロジェクトがあります。

ステップ2—Dropzoneコンポーネントを追加する

react-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;

このコードは、アプリケーションにドラッグアンドドロップ機能を提供します。

注: react-dropzoneはファイルをドラッグアンドドロップするように設計されていますが、デフォルトではドロップゾーンへのクリックイベントを受け入れ、ファイル選択のダイアログを起動します。

コンポーネントをReactアプリケーションに追加します。

src / App.js
import DropzoneComponent from './DropzoneComponent';

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

export default App;

アプリケーションを実行し、Webブラウザーで観察します。 Drag and drop your images hereというテキストのdivが表示されます。

さまざまなファイルをReactDropzoneコンポーネントにドラッグアンドドロップしてみてください。 このコードは現在、console.logを使用してファイルを表示しています。 アップロードされたファイルの情報には、namelastModifiedsizetypeが含まれます。

この時点で、デフォルト構成で動作するReactDropzoneコンポーネントがあります。 react-dropzoneドキュメント追加の構成オプション

ステップ3—Dropzoneコンポーネントのスタイリング

デフォルトでは、react-dropzoneにはスタイルがありません。 ドキュメントには、フレックスボックスと破線の境界線の組み合わせを使用して、ファイルをドラッグアンドドロップする領域をユーザーに示す一般的な外観のスタイルが記載されています。

react-dropzoneは、コンポーネントがアクティブに対話された場合(isDragActive)、ファイルを受け入れた場合(isDragAccept)、またはファイルを拒否した場合(isDragReject)の小道具もサポートします。 。

DropzoneComponentに再度アクセスし、isDragActiveisDragAccept、およびisDragRejectをJPEGおよびPNG画像ファイルタイプに適用する場合に使用するように変更します。

src / DropzoneComponent.js
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;

このコードは次の結果を生成します。

Screenshot of React Dropzone with custom styles

承認と拒否のコンポーネントの外観を変更すると、ファイルが有効かどうかについてユーザーにフィードバックを提供するのに役立ちます。

ステップ4—画像プレビューを追加する

プレビューは、コンポーネントにドラッグアンドドロップされた画像のコピーです。 これは、ユーザーが選択した画像ファイルの内容を確認するための視覚的なフィードバックをユーザーに提供するのに役立ちます。

プレビューはバージョン7.0.0で削除されましたが、ドキュメントには、Object.assign()URL.createObjectURL()の組み合わせでプレビューを読み直すための代替手段が記載されています。

DropzoneComponentに再度アクセスし、previewを使用するように変更します。

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)を呼び出して、プレビューが不必要に保存されないようにする必要があります。

これで、1つまたは複数のファイルがドロップされるたびに、ファイルが状態に追加され、プレビューが表示されます。

結論

このチュートリアルでは、react-dropzoneと、それをReactアプリケーションで使用して、ファイルのアップロードに高度なドラッグアンドドロップ機能を提供する方法を紹介しました。

Reactの詳細については、 React.js シリーズのコーディング方法をご覧になるか、Reactトピックページで演習やプログラミングプロジェクトを確認してください。