Skip to content

Guide · Open source

How to use react-dropzone: install and build a drop zone

Updated · written with AI from the project's own documentation and checked against our catalogue data

react-dropzone is a small React library that turns any element into a drop area for files dragged in from your computer, and opens a normal file picker when the area is clicked. This guide shows you how to install it, wire up the useDropzone hook, read the selected files and open the file dialog from code. It is written for React developers; no prior experience with drag-and-drop APIs is needed.

react-dropzonereact-dropzone/react-dropzone · ★ 11k · MIT

Quick start

  1. 1Check prerequisites. Make sure Node.js, npm or yarn, and a React project are available.
  2. 2Install the package. Run npm install react-dropzone or yarn add react-dropzone in your project folder.
  3. 3Import the hook. Import useDropzone from react-dropzone in the component where you want the drop area.
  4. 4Define an onDrop callback. Write a function that receives the accepted files, wrapped in useCallback.
  5. 5Spread the props. Apply getRootProps to a container element and getInputProps to an input inside it.
  6. 6Read file contents if needed. Use the FileReader API inside onDrop to read each file's contents.

Install react-dropzone with npm or yarn

You need Node.js, npm or yarn, and an existing React project. The library is installed from npm and ships as ESM and CommonJS with TypeScript types included, so it works with modern bundlers such as Vite, webpack and Rspack.

npm install react-dropzone yarn add react-dropzone

Create a drop zone with the useDropzone hook

The hook returns getRootProps and getInputProps. Spread the root props onto a container element and the input props onto an <input> inside it. The onDrop callback receives the accepted files. The isDragActive flag lets you change the text while a file is dragged over the area.

  • getRootProps() can go on any element you choose.
  • getInputProps() must go on an <input>, otherwise opening a file dialog will not be possible.
  • Wrap callbacks in useCallback so the hook is not re-created on every render.
import React, {useCallback} from "react"; import {useDropzone} from "react-dropzone"; function MyDropzone() { const onDrop = useCallback(acceptedFiles => { // Do something with the files }, []); const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop}); return ( <div {...getRootProps()}> <input {...getInputProps()} /> {isDragActive ? <p>Drop the files here ...</p> : <p>Drag 'n' drop some files here, or click to select files</p>} </div> ); }

Use the Dropzone wrapper component instead of the hook

If you prefer a component, the library also provides a Dropzone wrapper for the hook. It passes the same getRootProps and getInputProps functions to a render function as children. Wrapping the output in a section element is optional and is only shown as an example in the documentation.

import React from "react"; import Dropzone from "react-dropzone"; <Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}> {({getRootProps, getInputProps}) => ( <section> <div {...getRootProps()}> <input {...getInputProps()} /> <p>Drag 'n' drop some files here, or click to select files</p> </div> </section> )} </Dropzone>;

Read the contents of dropped files

The hook gives you File objects, not file contents. To read contents, the documentation uses the browser's FileReader API. Create a reader for each file, set handlers for abort, error and load, then call readAsArrayBuffer. The result is available in reader.result inside the load handler.

  • onabort logs when reading is aborted.
  • onerror logs when reading fails.
  • onload receives the contents in reader.result.
import React, {useCallback} from "react"; import {useDropzone} from "react-dropzone"; function MyDropzone() { const onDrop = useCallback(acceptedFiles => { acceptedFiles.forEach(file => { const reader = new FileReader(); reader.onabort = () => console.log("file reading was aborted"); reader.onerror = () => console.log("file reading has failed"); reader.onload = () => { // Do whatever you want with the file contents const binaryStr = reader.result; console.log(binaryStr); }; reader.readAsArrayBuffer(file); }); }, []); const {getRootProps, getInputProps} = useDropzone({onDrop}); return ( <div {...getRootProps()}> <input {...getInputProps()} /> <p>Drag 'n' drop some files here, or click to select files</p> </div> ); }

Pass your own props and refs safely

Props you add to the root element should be passed through getRootProps rather than set directly on the element, so they do not override the library's props or get overridden by them. A custom onClick runs before the internal one, so you can stop the internal handler with stopPropagation. Do not set a ref prop on the elements that receive the props; instead read rootRef and inputRef from the hook.

To open the file dialog from code, use the Dropzone component and set a ref on it. That ref exposes an open method.

  • Use getRootProps({onClick, role, "aria-label"}) to add your own attributes.
  • Read rootRef and inputRef from useDropzone() instead of setting ref yourself.
  • Pass refKey (for example "innerRef") to getRootProps if your styled component needs it.
import React, {createRef} from "react"; import Dropzone from "react-dropzone"; const dropzoneRef = createRef(); <Dropzone ref={dropzoneRef}> {({getRootProps, getInputProps}) => ( <div {...getRootProps()}> <input {...getInputProps()} /> <p>Drag 'n' drop some files here, or click to select files</p> </div> )} </Dropzone>; dropzoneRef.current.open();

Test components that use react-dropzone

The library makes some drag and drop callbacks asynchronous so that file retrieval can use promises. Because of this, the README recommends testing components with react-testing-library and wrapping the events in act. The example below creates a File and checks that onDragEnter is called after a dragenter event.

import React from "react"; import Dropzone from "react-dropzone"; import {act, fireEvent, render} from "@testing-library/react"; test("invoke onDragEnter when dragenter event occurs", async () => { const file = new File([JSON.stringify({ping: true})], "ping.json", {type: "application/json"}); const onDragEnter = jest.fn(); const ui = ( <Dropzone onDragEnter={onDragEnter}> {({getRootProps, getInputProps}) => ( <div {...getRootProps()}> <input {...getInputProps()} /> </div> )} </Dropzone> ); const {container} = render(ui); });

What people use it for

  • Letting users drop image files onto a form in a React web app.
  • Offering a click-to-select fallback next to drag and drop for file uploads.
  • Building a custom-styled upload area where you control the markup and CSS.
  • Reading the contents of a selected JSON or text file in the browser with FileReader.
  • Opening the file dialog from a button elsewhere on the page through the Dropzone ref.

Frequently asked questions

How do I install react-dropzone?

Install it from npm with npm install react-dropzone, or with yarn add react-dropzone. You need Node.js and a React project. The package includes TypeScript types.

Does react-dropzone work with TypeScript?

Yes. The README states that react-dropzone ships with TypeScript types included. It is also written in TypeScript.

How do I get the file contents after dropping a file?

The hook returns File objects. To read contents, use the browser FileReader API inside your onDrop callback, as shown in the documentation, and read reader.result in the onload handler.

Why doesn't the file picker open when I click the drop area?

The README says that if you omit rendering an input and/or binding getInputProps(), opening a file dialog will not be possible. Make sure an input element receives the props from getInputProps().

Does react-dropzone include a progress bar or resumable uploads?

The README describes only the drop zone and file handling. It does not describe progress bars or resumable uploads, so you would need to build those yourself or choose a different tool.

What are alternatives to react-dropzone?

Projects comparable to react-dropzone include react-filepond, react-uploady and filepond. Choose based on whether you want a finished upload widget or only a drop area you style yourself.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

react-dropzone suits React developers who want a drop area with click-to-select fallback and full control over the markup and styling. It is less suitable if you need a finished upload widget with progress bars and resumable uploads, or if you are not building with React.

Install options & downloads