All hooks / Events and input

useFileDrop

336 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

Turns an element into a drop zone for files, and reports when files are dragged over it.

isOver does not flicker when the pointer moves over child elements (it counts enter/leave pairs). Only reacts to drags that carry files, so dragging text or links inside the page is unaffected. Prevents the browser from opening a file dropped on the zone. Returns a callback ref for the element.

Import

import { useFileDrop } from '@vincent.ri/react-tils'
// or only this hook
import { useFileDrop } from '@vincent.ri/react-tils/useFileDrop'

Usage

const [ref, isOver] = useFileDrop((files) => upload(files.filter((f) => f.type.startsWith('image/'))))
return (
  <div ref={ref} className={isOver ? 'zone active' : 'zone'}>
    Drop images here, or <input type="file" accept="image/*" multiple onChange={(e) => upload([...e.target.files!])} />
  </div>
)

Live demo

Drag files from your desktop onto the box.

drop files here

When to use it

An upload area, an "import file" panel, or dropping images into an editor.

When not to

A plain <input type="file"> is enough; keep one anyway as the keyboard and screen-reader accessible way to pick files. Filter file types and sizes in onDrop; the browser doesn't.

API

function useFileDrop<T extends HTMLElement = HTMLElement>(onDrop: (files: File[], event: DragEvent) => void, options?: {
  enabled?: boolean;
}): [(element: T | null) => void, boolean]
ParameterDescription
onDropCalled with the dropped files. Can change every render.
optionsenabled: accept drops while true. Default true.

Returns [ref, isOver]. Pass ref to the drop zone's ref prop.

Browser support

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
Drag and drop filesWidely available3+12+3.6+4+18+3.2+

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).