Skip to content

useDropzone

Drag & drop zone with a prop-getter API. Does not upload; it only collects files and hands them to onDrop.

ts
function useDropzone(options: DropzoneOptions): DropzoneState

Pair it with useUploader:

tsx
const dropzone = useDropzone({
  onDrop: uploader.addFiles,
  accept: ['image/*', '.pdf'],
});

Options

OptionTypeDefaultDescription
onDrop(files: File[]) => voidrequiredAccepted files
onDropRejected(rejections) => voidRejected files from this event
acceptstring[]MIME / extension filter
multiplebooleantrueFile dialog allows multiple
disabledbooleanfalseIgnore click, drag, and input
noClickbooleanfalseDrag only; no click-to-open
noDragbooleanfalseClick only; ignore drag
maxFilesnumberCap for this drop/select only
maxFileSizenumberMax bytes
minFileSizenumberMin bytes
validatorFileValidatorCustom validation

Dropzone maxFiles does not know about files already in the uploader. Enforce the global cap on useUploader.

Returns

PropertyTypeDescription
getRootProps(props?) => propsSpread on the container
getInputProps(props?) => propsSpread on a hidden <input>
isDragActivebooleanPointer is dragging over the root
isDragAcceptbooleanDragged items look accepted
isDragRejectbooleanDragged items look rejected
open() => voidOpen the file dialog

getInputProps sets type="file", display: none, accept, multiple, and a ref. You still need to render <input {...getInputProps()} /> inside the root (or anywhere) so click-to-select works.

Example

tsx
const dropzone = useDropzone({
  onDrop: uploader.addFiles,
  onDropRejected: (rejections) => console.warn(rejections),
  accept: ['image/*'],
  maxFileSize: 10 * 1024 * 1024,
});

const className = [
  'dropzone',
  dropzone.isDragActive && 'is-active',
  dropzone.isDragReject && 'is-reject',
]
  .filter(Boolean)
  .join(' ');

return (
  <div {...dropzone.getRootProps()} className={className}>
    <input {...dropzone.getInputProps()} />
    {dropzone.isDragReject
      ? 'These files are not allowed'
      : dropzone.isDragActive
        ? 'Drop the files here'
        : 'Drag & drop, or click to browse'}
  </div>
);

The root is tabIndex={0} and opens the dialog on Enter / Space. getRootProps / getInputProps merge extra props you pass in; library handlers win for drag/drop/change.

During drag, accept/reject highlighting uses MIME types from dataTransfer.items. Extension-only accept patterns (.pdf) are applied on drop, not reliably while hovering. See Validation.

Released under the MIT License.