react-dropzone-vv のご紹介
react-dropzoneの後継packageを作成しており、開発開始から2ヶ月ほど経って仕様が固まってきたので紹介します。
react-dropzone-vvというpackage名で、以下のリンクからドキュメントにアクセスできます。
ドキュメント
GitHub
モチベーション
同じ機能を提供するpackageとしてはreact-dropzoneが有名でしょう。私も業務、個人開発の両方でお世話になってきました。しかし、2024年現在、2年近く更新が止まっており、今後のメンテナンスが継続されそうにありません。
そこでreact-dropzoneと同じ機能を作成することにし、packageとして公開しました。
特徴
react-dropzone-vvはファイルの選択にだけ集中し、選択されたファイルなどの状態を保持しません。これによってpackageはシンプルな実装を保つことができ、ユーザーは自由度の高い使い方ができます。
react-dropzoneの多くの機能をカバーしています。accept, disabled, multiple, noClick, noDragなどの指定はもちろん、onDragEnter, onDragOver, onDragLeave, onDrop, onSelect, onErrorなどのコールバック関数も用意されてます。
また、reactのバージョンは17以上に対応しています。古いバージョンの対応予定は無いです。これによってpackage自体のコードは、昔のreactを知らない人でも読みやすいと思います。
使い方
ドキュメントに詳しく書いてあるので、そちらをご覧ください。ここでは簡単にご紹介します。コード全体は以下のようになります。
import { FC, useState } from "react"
import {
useReactDropzoneVV,
ReactDropzoneVV,
RejectedClassifiedFile,
OnSelectProps,
} from "react-dropzone-vv"
export const Basic: FC = () => {
const [acceptedFiles, setAcceptedFiles] = useState<File[]>([])
const [fileRejections, setFileRejections] = useState<
RejectedClassifiedFile[]
>([])
const reactDropzoneVV = useReactDropzoneVV()
const handleSelect = (props: OnSelectProps) => {
setAcceptedFiles(props.acceptedFiles)
setFileRejections(props.fileRejections)
}
const handleError = (e: Error) => {
console.log(e)
}
return (
<section style={{ border: "solid", padding: "1rem" }}>
<ReactDropzoneVV
reactDropzoneVV={reactDropzoneVV}
onSelect={handleSelect}
onError={handleError}
>
<div
style={{
padding: "2rem",
border: "dashed",
backgroundColor: reactDropzoneVV.isDragging ? "#737373" : "#404040",
}}
>
<p>Drag & drop some files here, or click to select files</p>
</div>
</ReactDropzoneVV>
<div>acceptedFiles</div>
<ul>
{acceptedFiles.map((acceptedFile, index) => (
<li key={index}>{acceptedFile.name}</li>
))}
</ul>
<div>fileRejections</div>
<ul>
{fileRejections.map((fileRejection, index) => (
<span key={index}>
<li>{fileRejection.file.name}</li>
<ul>
<li>{fileRejection.rejectedCode}</li>
</ul>
</span>
))}
</ul>
</section>
)
}
ドラッグアンドドロップなどで選択されたファイルを保持するstateを作成しています。
const [acceptedFiles, setAcceptedFiles] = useState<File[]>([])
const [fileRejections, setFileRejections] = useState<
RejectedClassifiedFile[]
>([])
useReactDropzoneVVはドラッグ中などのstateを保持したり、input要素のrefを保持するのに使われています。
const reactDropzoneVV = useReactDropzoneVV()
ReactDropzoneVVコンポーネントに渡します。デフォルトでファイルの選択はクリックから選択とドラッグアンドドロップで選択できますが、onSelectはどちらで選択されたときも実行されるコールバック関数です。基本的にはonSelectを使用します。
<ReactDropzoneVV
reactDropzoneVV={reactDropzoneVV}
onSelect={handleSelect}
onError={handleError}
>
その他にaccept, disabled, multiple, noClick, noDragなどを指定できます。acceptはmdnの仕様と同じで、拡張子やmimeタイプをカンマ切りで指定できます。
例
accept="image/png,.webp"
ドキュメントにはこの他にも、複数のデモとコード例を用意しています。
おまけの技術的な話
使用している技術一覧
- vite
- vitepress ドキュメント作成
- vitest テスト
- typescript
依存関係が少ないのでこんな感じです。viteとvitepressを使用したpackage開発は別で記事にしています。この2つを組み合わせた開発体験は良かったです。
Discussion