ファイルアップロードUI設計のややこしさときたら…。<input type="file" />
で済むのなら、なんと明快なことか。そういう覚えはないだろうか。
<input type="file" />
だけであってもボタンとファイル名のスタイルを制御しなければならない。ブラウザそれぞれのUIも考慮しなければならない。そのうえユーザビリティの配慮からドラッグ&ドロップ機構が求められた場合、さらにややこしい。やれないことはないけど実装時間がかさむ。
これらネガティブな感情を払拭して余りある素晴らしいReactコンポーネントがある。
このエントリーでは、ドラッグ&ドロップのファイルアップロード実装を簡単にする「react-dropzone」を紹介したい。
react-dropzone について
react-dropzoneは、ドラッグ&ドロップでファイルアップロードUIを簡単に実装するためのReactコンポーネントだ。さらにReactアプリ開発のトレンドともいえるReact hooksに対応した作りをしている。ダウンロード数は、317,004(2020/1/6現在)と同種のものと比べると大きくリードしている。いわばファイルアップロードReactコンポーネントの決定版と言って差し支えないだろう。
https://react-dropzone.js.org/
特徴
- HTML5に準拠
- React hooksに対応
- スタイル適用が最小限
- 自由にスタイル適用が可能
react-dropzone に触る
それではreact-dropzoneの導入から確認していこう。
インストール
まずはパッケージをインストールする。package.json同階層で以下コマンドを実行してほしい。インストールするパッケージは「react-dropzone」のみでよい。
$ npm install --save react-dropzone
# or
$ yarn add react-dropzone
インポート
インポート方法は2パターン用意されている。まずは、React hooksを使う場合。React hooksを使うわけだからReactのバージョンは16.8以上である必要がある。
import {useDropzone} from 'react-dropzone';
もう一方は、ラッパーコンポーネントを使う場合。上記のReact hooksを使えない場合などの代替案と捉えるか、Class componentにしている場合は、いたし方なくラッパーコンポーネントをインポートしよう。
import Dropzone from 'react-dropzone';
デモンストレーション
下記ソースコードは公式にもある、もっともシンプルなドラッグ&ドロップファイルアップロード実装で、ファイルをエリアにドロップするとファイル名が表示されるというものだ。
import React from 'react';
import './App.css';
import {useDropzone} from 'react-dropzone';
function App () {
const {acceptedFiles, getRootProps, getInputProps} = useDropzone();
const files = acceptedFiles.map(file => (
<li>{file.path}</li>
));
return (
<div className="container">
<div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
<ul>
{files}
</ul>
</div>
);
}
export default App;
まとめ
ドラッグ&ドロップのファイルアップロード実装を簡単にする「react-dropzone」の紹介だった。
実装して気がつくことがある。それはスタイル適用する要素が思いのほか多く残されていること。これは悪い意味ではなくて好感が持てる箇所だと感じた。なぜなら、打ち消しのスタイルを記述することがなく、ソースコードに素直さを保てたからだ。対象要素にclassNameを与えることはできるが、これは決してreact-dropzoneが割り振るclassNameをオーバーライドするためのものではない。上書きする記述が混在しないシンプルなソースコードを保てて良い。ファイルアップロード要件がある場合は「react-dropzone」を検討してみてはいかがだろうか。
このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。