0
# React Dropzone
1
2
React Dropzone is a React library that provides simple HTML5-compliant drag-and-drop zones for file uploads. It offers a powerful `useDropzone` hook and convenient `Dropzone` component wrapper with extensive customization options, file validation, and comprehensive event handling.
3
4
## Package Information
5
6
- **Package Name**: react-dropzone
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install react-dropzone` or `yarn add react-dropzone`
10
11
## Core Imports
12
13
```typescript
14
import Dropzone, { useDropzone, ErrorCode, FileWithPath } from "react-dropzone";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const Dropzone = require("react-dropzone").default;
21
const { useDropzone, ErrorCode, FileWithPath } = require("react-dropzone");
22
```
23
24
## Basic Usage
25
26
```typescript
27
import React, { useCallback } from "react";
28
import { useDropzone } from "react-dropzone";
29
30
function MyDropzone() {
31
const onDrop = useCallback((acceptedFiles: File[]) => {
32
// Process the dropped files
33
console.log(acceptedFiles);
34
}, []);
35
36
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
37
38
return (
39
<div {...getRootProps()}>
40
<input {...getInputProps()} />
41
{isDragActive ? (
42
<p>Drop the files here...</p>
43
) : (
44
<p>Drag 'n' drop files here, or click to select files</p>
45
)}
46
</div>
47
);
48
}
49
```
50
51
## Architecture
52
53
React Dropzone is built around modern React patterns:
54
55
- **Hook-based API**: Primary interface through `useDropzone` hook (React 16.8+)
56
- **Component Wrapper**: Optional `Dropzone` component for render prop pattern
57
- **Event-driven Architecture**: Comprehensive drag and drop event handling
58
- **File Validation System**: Built-in validation for file types, sizes, and custom rules
59
- **Zero Dependencies**: Core functionality has no external dependencies beyond React
60
- **TypeScript Support**: Complete type definitions included
61
62
## Capabilities
63
64
### useDropzone Hook
65
66
The primary interface for creating drag-and-drop zones with full customization options.
67
68
```typescript { .api }
69
/**
70
* Creates a drag 'n' drop area with comprehensive configuration options
71
* @param options - Configuration options for the dropzone
72
* @returns State object with drag states, file arrays, and prop getter functions
73
*/
74
function useDropzone(options?: DropzoneOptions): DropzoneState;
75
76
interface DropzoneOptions {
77
/** Accepted file types as MIME type object (default: undefined - all files) */
78
accept?: Accept;
79
/** Allow multiple file selection (default: true) */
80
multiple?: boolean;
81
/** Prevent drops on document (default: true) */
82
preventDropOnDocument?: boolean;
83
/** Disable click to open file dialog (default: false) */
84
noClick?: boolean;
85
/** Disable keyboard file dialog triggers (default: false) */
86
noKeyboard?: boolean;
87
/** Disable drag and drop (default: false) */
88
noDrag?: boolean;
89
/** Stop drag event bubbling (default: false) */
90
noDragEventsBubbling?: boolean;
91
/** Minimum file size in bytes (default: 0) */
92
minSize?: number;
93
/** Maximum file size in bytes (default: Infinity) */
94
maxSize?: number;
95
/** Maximum number of files (default: 0 - unlimited) */
96
maxFiles?: number;
97
/** Disable the dropzone (default: false) */
98
disabled?: boolean;
99
/** Use File System Access API (default: false) */
100
useFsAccessApi?: boolean;
101
/** Auto focus the dropzone (default: false) */
102
autoFocus?: boolean;
103
/** Custom file aggregator function (default: fromEvent from file-selector) */
104
getFilesFromEvent?: (event: DropEvent) => Promise<Array<File | DataTransferItem>>;
105
/** Custom file validator (default: null) */
106
validator?: <T extends File>(file: T) => FileError | readonly FileError[] | null;
107
/** Callback when files are dropped */
108
onDrop?: <T extends File>(
109
acceptedFiles: T[],
110
fileRejections: FileRejection[],
111
event: DropEvent
112
) => void;
113
/** Callback when files are accepted */
114
onDropAccepted?: <T extends File>(files: T[], event: DropEvent) => void;
115
/** Callback when files are rejected */
116
onDropRejected?: (fileRejections: FileRejection[], event: DropEvent) => void;
117
/** Callback when drag enters */
118
onDragEnter?: (event: React.DragEvent<HTMLElement>) => void;
119
/** Callback when drag leaves */
120
onDragLeave?: (event: React.DragEvent<HTMLElement>) => void;
121
/** Callback when dragging over */
122
onDragOver?: (event: React.DragEvent<HTMLElement>) => void;
123
/** Callback when file dialog opens */
124
onFileDialogOpen?: () => void;
125
/** Callback when file dialog is cancelled */
126
onFileDialogCancel?: () => void;
127
/** Error handler */
128
onError?: (error: Error) => void;
129
}
130
131
interface DropzoneState {
132
/** Dropzone is focused */
133
isFocused: boolean;
134
/** Active drag is in progress */
135
isDragActive: boolean;
136
/** Dragged files are accepted */
137
isDragAccept: boolean;
138
/** Some dragged files are rejected */
139
isDragReject: boolean;
140
/** File dialog is open */
141
isFileDialogActive: boolean;
142
/** Array of accepted files */
143
acceptedFiles: readonly FileWithPath[];
144
/** Array of rejected files with errors */
145
fileRejections: readonly FileRejection[];
146
/** Reference to root element */
147
rootRef: React.RefObject<HTMLElement>;
148
/** Reference to input element */
149
inputRef: React.RefObject<HTMLInputElement>;
150
/** Get props for root container */
151
getRootProps: <T extends DropzoneRootProps>(props?: T) => T;
152
/** Get props for hidden file input */
153
getInputProps: <T extends DropzoneInputProps>(props?: T) => T;
154
/** Programmatically open file dialog */
155
open: () => void;
156
}
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
import { useDropzone } from "react-dropzone";
163
164
// Basic file upload
165
const basic = useDropzone({
166
onDrop: (files) => console.log("Dropped files:", files),
167
});
168
169
// With file type restrictions
170
const imageOnly = useDropzone({
171
accept: {
172
"image/*": [".jpeg", ".jpg", ".png", ".gif"],
173
},
174
onDrop: (files) => uploadImages(files),
175
});
176
177
// With size limits and multiple files
178
const documents = useDropzone({
179
accept: {
180
"application/pdf": [".pdf"],
181
"application/msword": [".doc", ".docx"],
182
},
183
minSize: 1024, // 1KB minimum
184
maxSize: 5242880, // 5MB maximum
185
maxFiles: 3,
186
onDropAccepted: (files) => handleAccepted(files),
187
onDropRejected: (rejections) => handleRejected(rejections),
188
});
189
```
190
191
### Dropzone Component
192
193
Convenience wrapper component using render prop pattern for the useDropzone hook.
194
195
```typescript { .api }
196
/**
197
* Convenience wrapper component for the useDropzone hook
198
* @param props - Dropzone options plus children render function
199
*/
200
function Dropzone(
201
props: DropzoneProps & React.RefAttributes<DropzoneRef>
202
): React.ReactElement;
203
204
interface DropzoneProps extends DropzoneOptions {
205
/** Render function that receives dropzone state */
206
children?(state: DropzoneState): React.ReactElement;
207
}
208
209
interface DropzoneRef {
210
/** Programmatically open file dialog */
211
open: () => void;
212
}
213
```
214
215
**Usage Examples:**
216
217
```typescript
218
import Dropzone from "react-dropzone";
219
220
// Basic usage with render prop
221
<Dropzone onDrop={(files) => console.log(files)}>
222
{({ getRootProps, getInputProps, isDragActive }) => (
223
<div {...getRootProps()}>
224
<input {...getInputProps()} />
225
{isDragActive ? (
226
<p>Drop files here...</p>
227
) : (
228
<p>Drag files here or click to browse</p>
229
)}
230
</div>
231
)}
232
</Dropzone>
233
234
// With imperative access via ref
235
const dropzoneRef = useRef<DropzoneRef>(null);
236
237
<Dropzone ref={dropzoneRef} onDrop={handleDrop}>
238
{({ getRootProps, getInputProps }) => (
239
<div {...getRootProps()}>
240
<input {...getInputProps()} />
241
<button onClick={() => dropzoneRef.current?.open()}>
242
Browse Files
243
</button>
244
</div>
245
)}
246
</Dropzone>
247
```
248
249
### File Validation and Error Handling
250
251
Built-in validation system with detailed error reporting for rejected files.
252
253
```typescript { .api }
254
/** Error codes for file validation failures */
255
enum ErrorCode {
256
FileInvalidType = "file-invalid-type",
257
FileTooLarge = "file-too-large",
258
FileTooSmall = "file-too-small",
259
TooManyFiles = "too-many-files",
260
}
261
262
interface FileError {
263
/** Human-readable error message */
264
message: string;
265
/** Error code for programmatic handling */
266
code: ErrorCode | string;
267
}
268
269
interface FileRejection {
270
/** The rejected file */
271
file: FileWithPath;
272
/** Array of validation errors */
273
errors: readonly FileError[];
274
}
275
276
interface FileWithPath extends File {
277
/** File path (when available) */
278
path?: string;
279
}
280
```
281
282
**Usage Examples:**
283
284
```typescript
285
import { useDropzone, ErrorCode } from "react-dropzone";
286
287
const { getRootProps, getInputProps, fileRejections } = useDropzone({
288
accept: { "image/*": [] },
289
maxSize: 1048576, // 1MB
290
onDropRejected: (rejections) => {
291
rejections.forEach(({ file, errors }) => {
292
console.log(`File ${file.name} rejected:`);
293
errors.forEach((error) => {
294
switch (error.code) {
295
case ErrorCode.FileInvalidType:
296
console.log("Invalid file type");
297
break;
298
case ErrorCode.FileTooLarge:
299
console.log("File too large");
300
break;
301
default:
302
console.log(error.message);
303
}
304
});
305
});
306
},
307
});
308
309
// Custom validator
310
const customValidation = useDropzone({
311
validator: (file) => {
312
if (file.name.includes("temp")) {
313
return {
314
code: "name-not-allowed",
315
message: "Temporary files are not allowed",
316
};
317
}
318
return null;
319
},
320
});
321
```
322
323
### Advanced Configuration
324
325
Advanced features for specialized use cases and enhanced user experience.
326
327
```typescript { .api }
328
interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {
329
/** Reference key for root element (default: "ref") */
330
refKey?: string;
331
[key: string]: any;
332
}
333
334
interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
335
/** Reference key for input element (default: "ref") */
336
refKey?: string;
337
}
338
339
interface Accept {
340
/** MIME type keys with array of file extensions */
341
[mimeType: string]: readonly string[];
342
}
343
344
type DropEvent =
345
| React.DragEvent<HTMLElement>
346
| React.ChangeEvent<HTMLInputElement>
347
| DragEvent
348
| Event
349
| Array<FileSystemFileHandle>;
350
```
351
352
**Usage Examples:**
353
354
```typescript
355
// File System Access API (modern browsers)
356
const modernFileAccess = useDropzone({
357
useFsAccessApi: true,
358
onDrop: (files) => console.log("Files selected:", files),
359
});
360
361
// Custom file processing
362
const customProcessor = useDropzone({
363
getFilesFromEvent: async (event) => {
364
// Custom file extraction logic
365
const items = Array.from(event.dataTransfer?.items || []);
366
return items
367
.filter((item) => item.kind === "file")
368
.map((item) => item.getAsFile())
369
.filter(Boolean);
370
},
371
});
372
373
// Preventing document drops globally
374
const secureDropzone = useDropzone({
375
preventDropOnDocument: true,
376
noDragEventsBubbling: true,
377
onDrop: (files) => secureUpload(files),
378
});
379
380
// Accessibility and keyboard support
381
const accessibleDropzone = useDropzone({
382
autoFocus: true,
383
noKeyboard: false, // Allow SPACE/ENTER to open dialog
384
onDrop: (files) => handleFiles(files),
385
});
386
```
387
388
389
## Types
390
391
```typescript { .api }
392
/** File with optional path information */
393
interface FileWithPath extends File {
394
path?: string;
395
}
396
397
/** Configuration for accepted file types */
398
interface Accept {
399
[mimeType: string]: readonly string[];
400
}
401
402
/** Union type for various drop events */
403
type DropEvent =
404
| React.DragEvent<HTMLElement>
405
| React.ChangeEvent<HTMLInputElement>
406
| DragEvent
407
| Event
408
| Array<FileSystemFileHandle>;
409
410
/** Error codes for file validation */
411
enum ErrorCode {
412
FileInvalidType = "file-invalid-type",
413
FileTooLarge = "file-too-large",
414
FileTooSmall = "file-too-small",
415
TooManyFiles = "too-many-files",
416
}
417
418
/** File validation error */
419
interface FileError {
420
message: string;
421
code: ErrorCode | string;
422
}
423
424
/** Rejected file with associated errors */
425
interface FileRejection {
426
file: FileWithPath;
427
errors: readonly FileError[];
428
}
429
```